Вопрос

Джоэл упомянул подсчет количества установленных битов в байте как вопрос программирования в своей книге Партизанское руководство по проведению собеседований, и рассказал о способе использования шаблонов, встречающихся в справочной таблице.Я написал об этом статью некоторое время назад после того, как нашел закономерность.

Обобщить:

Number of bits set in a byte in 16x16
0   1   1   2   1   2   2   3   1   2   2   3   2   3   3   4  
1   2   2   3   2   3   3   4   2   3   3   4   3   4   4   5  
1   2   2   3   2   3   3   4   2   3   3   4   3   4   4   5  
2   3   3   4   3   4   4   5   3   4   4   5   4   5   5   6  
1   2   2   3   2   3   3   4   2   3   3   4   3   4   4   5  
2   3   3   4   3   4   4   5   3   4   4   5   4   5   5   6  
2   3   3   4   3   4   4   5   3   4   4   5   4   5   5   6  
3   4   4   5   4   5   5   6   4   5   5   6   5   6   6   7  
1   2   2   3   2   3   3   4   2   3   3   4   3   4   4   5  
2   3   3   4   3   4   4   5   3   4   4   5   4   5   5   6  
2   3   3   4   3   4   4   5   3   4   4   5   4   5   5   6  
3   4   4   5   4   5   5   6   4   5   5   6   5   6   6   7  
2   3   3   4   3   4   4   5   3   4   4   5   4   5   5   6  
3   4   4   5   4   5   5   6   4   5   5   6   5   6   6   7  
3   4   4   5   4   5   5   6   4   5   5   6   5   6   6   7  
4   5   5   6   5   6   6   7   5   6   6   7   6   7   7   8  

Первая строка и столбец абсолютно одинаковы, и каждую позицию в таблице можно вычислить путем сложения первых значений в строке и столбце этой позиции.По этой причине вам нужна только таблица поиска с 16 записями для 8-битного числа, и вы можете использовать только первые 16 чисел.Затем, если вы хотите, например, посчитать установленные биты в числе 243, вам просто нужно сделать:

a = [0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4]
x = 243 / 16 => 15 # (int)
y = 243 % 16 => 3

a[x] + a[y] => 6

# Are there six bits set in the number 243?
243 = 11110011 # yep

Следующая закономерность, которую я заметил после этого, заключалась в том, что каждый раз, когда вы удваивали размер сетки NxN, каждый квадрант можно было вычислить путем добавления 0, 1, 1 и 2 к каждому квадранту соответственно, вот так:

# Make a 4x4 grid on the paper, and fill in the upper left quadrant with the values of the 2x2 grid.  
# For each quadrant, add the value from that same quadrant in the 2x2 grid to the array.  

# Upper left quad add 0 to each number from 2x2  
0   1   *   *  
1   2   *   *  
*   *   *   *  
*   *   *   *  

# Upper right quad add 1 to each number from 2×2  
0   1   1   2  
1   2   2   3  
*   *   *   *  
*   *   *   *  

# Lower left quad add 1 to each number from 2×2  
0   1   1   2  
1   2   2   3  
1   2   *   *  
2   3   *   *  

# Lower right quad add 2 to each number from 2×2  
0   1   1   2  
1   2   2   3  
1   2   2   3  
2   3   3   4  

Повторите этот процесс еще два раза, и сверху вы получите сетку 16x16, поэтому я решил, что должен быть какой-то алгоритм квадродерева, который позволит вам начать с сетки:

0 1
1 2

и, учитывая число N, на лету сгенерируйте справочную таблицу и вычислите количество битов.Итак, мой вопрос/проблема: Можете ли вы придумать алгоритм, позволяющий сделать именно это?

Это было полезно?

Решение 2

На основе кода Роберта здесь, это можно сделать даже без деления или модуля, заменив их одним сдвигом и одним И, вот так:

a = [0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4]
x = 243 >> 4 # 15 (same as dividing by 16)
y = 243 & 0x0f # 3 ( same as modding by 16)

result = a[x] + a[y] # 6 bits set 

Или в С:

const unsigned char oneBits[] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};

unsigned char CountOnes(unsigned char x)
{
    unsigned char results;
    results = oneBits[x&0x0f];
    results += oneBits[x>>4];
    return results
}

Для целого числа любого размера вы можете просто перебрать байты и выполнить быстрый поиск, например:

def bits(n)
    a = [0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4]
    a[n >> 4] + a[n & 0x0f]
end

def setBits(n)
   total = 0
   while(n > 0)
       total += bits(n&0xff)
       n >>= 8
   end
   total
end

setBits(6432132132165432132132165436265465465653213213265465) # 78 bits set

Я удовлетворен этим ответом.Я знал, что что-то более сложное и в стиле квадродерева не будет эффективным, я просто подумал, что это достойный мысленный эксперимент.

Другие советы

Это глупый вопрос!В первом примере, где вы вычислили количество битов, заданных с использованием таблицы из 16 записей вместо 256, нет ничего волшебного!Все, что вам нужно сделать, это подсчитать количество битов, установленных в первых четырех битах байта (первый полубайт), а затем во втором полубайте, сложив их вместе.x/16 — первый полубайт, x%16 — второй полубайт.

Если вы повторите процесс, теперь у вас есть таблица поиска для двух битов, и вы просто делаете это четыре раза, по одному для каждой пары.В крайнем случае, вы можете просто сложить все биты один за другим и получить очевидный ответ.

Весь смысл таблицы поиска состоит в том, чтобы избежать добавления.

Извините за поздний пост, но я только что нашел вызов.Мой 0,02 доллара (грубая сила)

Private Sub Button1_Click(ByVal sender As System.Object, _
                          ByVal e As System.EventArgs) Handles Button1.Click

    For x As Integer = 0 To 255
        Debug.WriteLine(bitsOn2(CByte(x)) & " " & Convert.ToString(x, 2).PadLeft(8, "0"c))
    Next

End Sub

Private Function bitsOn(ByVal aByte As Byte) As Integer
    Dim aBit As Byte = 1
    For z As Integer = 0 To 7
        If (aByte >> z And aBit) = aBit Then bitsOn += 1
    Next
End Function

Dim aDict As New Dictionary(Of Integer, Integer)
Private Function bitsOn2(ByVal aByte As Byte) As Integer
    If aDict.Count = 0 Then 'init dictionary
        For x As Integer = 0 To 255
            aDict.Add(x, bitsOn(CByte(x)))
        Next
    End If
    Return aDict(aByte)
End Function
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top