Как я могу проверить вес Хэмминга без преобразования в двоичный файл?
Как я могу получить число "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
Ответы
Ответ 1
IMO, хорошим подходом было бы использовать справочную таблицу - создать словарь, который преобразует байты в число 1 (вы можете использовать код, который вы опубликовали для его создания, его нужно будет запускать только один раз) и затем используйте что-то вроде этого:
def number_of_ones(n):
sum = 0
while n != 0:
sum += lookup_table[n & 0xff]
n >>= 8
return sum
Я считаю, что это довольно хороший компромисс между пространством и временем выполнения.
Ответ 2
Я не программист на питоне, но, надеюсь, этого вам будет достаточно.
c = 0
while n:
c += 1
n &= n - 1
return c
В то время как немного неясное, основным преимуществом является скорость и простота. Цикл while повторяется только один раз для каждого бита, установленного в 1 в n.
Ответ 3
Вы не можете сделать это вычислительно менее сложным. Это будет O (n) число бит, или, как показал ответ с трюком, O (n) число бит, установленное в 1; но если все номера, которые вы используете, являются особым случаем, последний должен в среднем иметь n/2, поэтому оба этих числа O (n) совпадают.
И трюк lookup-table, конечно, на самом деле ничего не делает для вычислительной сложности; он просто оплачивает время с пространством, но не меняет основную экономику, а именно, что вы должны каждый раз проверять каждый бит, и нет никакого способа обойти это. Вы не можете логически ответить на вопрос о битах в номере, не проверяя каждый из них.
Теперь я полагаю, что я немного неаккуратно, так как многие из этих примеров на самом деле являются O (n ^ 2), так как в Python вам нужно одновременно проверять все число, поэтому с длинным целым числом Python, скажем, 100 байт, a + или an и/или операция будут смотреть на каждый байт по крайней мере один раз, и это будет повторяться снова и снова, пока число не будет уменьшено до нуля (в схемах, описанных выше), так что они снова действительно O (n ^ 2). Я не уверен, что Python разрешит здесь истинное решение O (n).
В любом случае: если вы действительно спрашиваете о сложности вычислений, что конкретно означает большой анализ O, это ваш ответ.: -)
Ответ 4
Если вы хотите сделать это в одной строке, вы можете использовать:
sum( [x&(1<<i)>0 for i in range(32)] )
Ответ 5
Если вы действительно обеспокоены скоростью, запросите код в C (см. этот вопрос для чего) и интерфейс с реализацией C, используя что-то вроде ctypes.
Ответ 6
p = lambda 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
Ответ 7
Здесь:
def битCount (int_no):
c = 0
while(int_no):
int_no &= (int_no - 1)
c += 1
return c
Это может быть старый и эффективный способ сделать это... изначально реализованный в C (у Algo есть имя, которое я не могу вспомнить). Он отлично работает для меня, надеюсь, что это будет для любого другого человека.