Как я могу проверить вес Хэмминга без конвертации в 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