簡體   English   中英

這種神奇的位計數方法是如何工作的?

[英]How does this magic bit counting method work?

在處理 XKCD 愚人節的 skein哈希沖突問題時,我遇到了一種奇怪的、快速的、乘法計算單詞中設置位的方法

c = (v * 0x200040008001ULL & 0x111111111111111ULL) % 0xf;

為什么這有效/發生了什么? 我們可以推廣這個方法嗎(例如,從問題中處理我們的 128 位值)?

另外,我不禁認為它與這個關於使用巧妙的幻數移動位的問題有關。

這實際上不計算 32 位字中的設置位,因為模運算符的性質輸出必須小於0xf (也稱為 15)。

首先,讓我們特別注意模運算符。 為什么是15? 為什么我們要屏蔽每個 nybble 中的最低有效位?

好吧,請注意,對於某些k ,每個最低有效 nybble 位的值為16^k k 需要注意的是16 mod 15是1,因此16^k mod 15是1的任意非負整數值k

這很方便,因為這意味着16^k1 + 16^k2 + ... + 16^kn = n mod 15

換句話說,由於上述數學運算,模運算符有效地計算設置的最低有效 nybble 位的數量——只要 nybble 中沒有設置其他位。 (他們只會礙事。)

但是,我們不想只計算 nybbles 中特殊格式的位。 我們想要計算設置在任意值中的位數。 訣竅是通過移動這些位來將這些值位放入那些特殊格式的 nybbles 中。 nybble 的最終順序並不重要,只要我們可以將一位值移動到一個 nybble 中即可。 理論上,由於我們使用 64 位值進行計數,我們可以將 16 位值中的每一位映射到它自己的 nybble,總共4 * 16 = 64位,正好在我們的 64 位允許范圍內。 但是,請注意,因為我們使用的是模 15,所以任何具有 15 位或 16 位設置位的值將分別顯示為 0 或 1。

現在讓我們重新關注這個奇怪的常量: 0x200040008001ULL

讓我們注意設置了哪些位(其中位0是最低有效位):0、15、30 和 45。您可能已經注意到它們以 15 位為間隔。 這很方便,因為對於小於2^15值,此乘法只會在 64 位字中創建該值的多個移位副本。 但是當值變得等於或大於2^15 ,副本開始疊加重疊,這對於特別計數位不再有用。 不過,這沒關系,因為通過這種模運算,我們甚至無法可靠地計算出多達 15 位的信息。 (然而,如果模運算的結果是 0,我們知道所有位都被設置,或者沒有,再次假設我們只得到小於 2^15 的值。)

因此,我們在 64 位寄存器中移動了 15 位數字的副本。 第二步是掩碼僅提取每個 nybble 的最低有效位。 因為每個 nybble 的最低有效位等於1 (mod 15)所以模運算符有效地計算了 nybble 中設置的最低有效位的數量。

剩下的唯一細節是確保我們的 15 位數字中的每一位都恰好落在最低有效 nybble 位槽中一次。

讓我們檢查:

The first bit set, 0, doesn't shift the value at all, giving our value bits 0 through 14.
This places value value bits 0, 4, 8, and 12 in a least significant nybble bit slot.

The second bit set, 15, gives our value bits 15 through 29.
This places our value bits 1, 5, 9, and 13 in bits 16, 20, 24, and 28.

The third bit set, 30, gives our value bits 30 through 44.
This places our value bits 2, 6, 10, and 14 in bits 32, 36, 40, and 44.

Finally, the forth bit set, 45, gives our value bits 45 through 59.
This places our value bits 3, 7, 11, and 15 in bits 48, 52, 56, and 60.

Bits accounted for:
0, 4, 8,  and 12
1, 5, 9,  and 13
2, 6, 10, and 14
3, 7, 11, and 15

很容易直觀地驗證這是否映射了 16 位。 但是,請注意掩碼實際上是 15 1 ,而不是 16。因此,放置在最后一個 nybble 中的位(從位 60 開始,代表我們值的第 15 位,即 16 位值的最高位)實際上被忽略了。

這樣,整個技術就完成了:

  1. 使用乘法將每個位映射到最低有效 nybble 位。
  2. 使用掩碼僅選擇所需的 nybble 位。
  3. 請注意,最低有效 nybble 位等效於1 (mod 15)
  4. 因此, (mod 15)將簡單地將這些位加在一起……最多設置 14 位。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM