Как я могу проверить вес Хэмминга без преобразования в двоичный файл?

Как я могу получить число "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 есть имя, которое я не могу вспомнить). Он отлично работает для меня, надеюсь, что это будет для любого другого человека.