Как я могу проверить вес Хэмминга без конвертации в binary?
Как я могу получить число " 1 " s в двоичном представлении числа без фактического преобразования и подсчета?
например
def number_of_ones(n):
# do something
# I want to MAKE this FASTER (computationally less complex).
c = 0
while n:
c += n%2
n /= 2
return c
>>> number_of_ones(5)
2
>>> number_of_ones(4)
1
7 ответов
IMO, хорошим подходом было бы использовать таблицу поиска-создать словарь, который преобразует байты в число 1 (Вы можете использовать код, который вы опубликовали, чтобы сгенерировать его, ему нужно будет запустить только один раз), а затем использовать что-то вроде этого:
def number_of_ones(n):
sum = 0
while n != 0:
sum += lookup_table[n & 0xff]
n >>= 8
return sum
Я считаю, это достаточно хороший компромисс между пространством и временем.
Я не программист python, но, надеюсь, вам будет достаточно следовать.
c = 0
while n:
c += 1
n &= n - 1
return c
в то время как немного неясно, это основное преимущество-скорость и простота. Цикл while повторяется только один раз для каждого бита, установленного в 1 в n.
вы не можете сделать это вычислительно менее сложным. Это будет O(n) число битов, или, как показал ответ с помощью & trick, O(n) число битов, равное 1; но если все числа, которые вы используете, не являются частным случаем, последнее должно быть в среднем n/2, поэтому оба этих o (n) числа одинаковы.
и трюк с таблицей поиска, конечно, на самом деле ничего не делает для вычислительной сложности; это просто оплата за время с пространством, но без изменения основная экономика, которая заключается в том, что вы должны изучить каждый бит один раз как-то и нет никакого способа обойти это. Вы не можете логически ответить на вопрос о битах в числе, не проверив каждый из них.
теперь, я полагаю, я немного небрежен, так как многие из этих примеров на самом деле O (n^2), так как в Python вы должны исследовать все число сразу, поэтому с длинным целым числом Python, скажем, 100 байт, a + или & или A / операция будет смотреть на каждый байт хотя бы один раз, и это будет происходить снова и снова, пока число не будет уменьшено до нуля (в схемах, описанных выше), поэтому это, опять же, действительно o(n^2) операции. Я не уверен, что Python позволит здесь истинное решение O(n).
в любом случае: если вы действительно спрашиваете о вычислительная сложность, что конкретно означает анализ big-O, это ваш ответ. :-)
Если вы хотите сделать это в одну строку, вы можете использовать:
sum( [x&(1<<i)>0 for i in range(32)] )
Если вы действительно беспокоитесь о скорости, Закодируйте ее в C (см. этот вопрос как), и интерфейс с реализацией C, используя что-то вроде ctypes.
здесь:
деф число битов(int_no):
c = 0
while(int_no):
int_no &= (int_no - 1)
c += 1
return c
Это может быть старый и эффективный способ сделать это... первоначально реализован в C (Algo имеет имя, которое я не могу вспомнить). Он отлично работает для меня, надеюсь, что это для любого другого человека
p= лямбда n: n и 1+p(n&(n-1))
Это использует короткое замыкание и рекурсию, когда n больше 0, он переключается на вычисление 1+p(n&(n-1)), где p(n&(n-1)) вызывается и так далее, когда n равно 0, он возвращает 0. Сложность O (n), так как она выполняет количество раз, когда число единиц существует в двоичном файле.
пример: p (9)=1+p (8)=1+1+p(0)=1+1+0=2