2009-11-27 55 views
0

如何使用移位運算符和加法將n的數字除以24使用移位運算符除以任意數字

n % 24 == 0

+2

你爲什麼要這麼做? – 2009-11-27 10:37:54

+0

對於需要使用128位數字操作的ACM ICPC問題(因此必須手動執行)。移動和添加手動操作不是很困難。 – Etan 2009-11-27 10:42:22

+0

您顯示的代碼計算單個布爾值,實際上與divsion很少有關係。 24是二進制11000.現在很明顯,11011000%11000 == 0. 11011000 = 11000000 + 11000,11000000%11000 == 0和110000%11000 == 0.這可以概括爲測試'(x %N == 0)'其中N是一個常數。 – MSalters 2009-11-27 11:52:52

回答

2

這個工作原理是先找到結果的最高位,然後回去工作。

int div24(int value) { 
    // Find the smallest value of n such that (24<<n) > value 
    int tmp = 24; 
    for (int n = 0; tmp < value; ++n) 
    tmp <<= 1; 
    // Now start working backwards to find bits of the result. This is O(i). 
    int result = 0; 
    while(value != 0) { 
    tmp >>= 1; 
    result <<= 1; 
    if (value > tmp) { // Found one bit. 
     value -= tmp; // Subtract (24<<i) 
     result++; 
    } 
    } 
    return result; 
} 

例子:

Value = 120 : n = 2 
Step 0: tmp = 96, result = 0, value = 24, result = 1 
Step 1: tmp = 48, result = 2 
Step 2: tmp = 24, result = 4, value = 0, result = 5 
0

雖然這是毫無疑問的24個聰明的黑客,使用移位運算符[和/或減法]只有真正使爲2的冪感覺即便如此,其更可能迷惑讀者而不是用現代編譯器生成更高效的代碼。

+0

哦......你認爲這個問題是關於一個聰明的方式嗎?那麼改變一切...... :) – 2009-11-27 10:44:25

+0

@帕斯卡爾:沒有解釋,這聽起來很有家庭作業。你的好回答,+1 – 2009-11-27 10:55:50

4

該分部的鉛筆和紙張算法僅使用「移位」(基10個移位)和減法。你可以在基數2中做同樣的事情。

對不起,我找不到算法的鏈接,但你應該從小時候開始學習它。

編輯:實際上,因爲增加是價格便宜,你不必試圖逐個提取正確的數字,這樣可以簡化算法有點...

假設積極被除數和除數..

取兩個直接大於除數(這裏是32)的冪。

很容易用這個2的冪數來劃分你的數字。假設該部門生產​​。 減去k1*24從號碼(可撥打其餘r1)和迭代...

當您已經獲得​​,k2,... kn數字,其餘rn不再包含32,做最後的檢查,看是否rn包含24.

該部門的結果是k1+k2+...+kn (+1 if 24 fits in rn)

+0

請注意,這個算法優雅地處理了你除以2的冪的特殊情況:在這種情況下,它收斂在一個步驟中。如果除數是2加1的冪,則可以採取對數減法/加法。 – 2009-11-27 10:58:01

+0

240/32 = 7; 240-32 * 7 = 16這是<24.期望的結果是10.似乎沒有工作。 – Etan 2009-11-27 12:49:07

+0

@ int3,Etan:爲了成爲鉛筆和紙張算法的簡化版本,「k1 * 32」當然應該被讀作「k1 * 24」。我編輯了答案來解決它。 – 2009-11-27 13:21:27

1
int 
div24(int value) { 
    int result = 0; 
    while (value >= 24) {  
     int accum = 24; 
     int tmp = 1;  
     while (accum + accum <= value) { 
     accum += accum; 
     tmp += tmp; 
     } 
     value -= accum;  
     result += tmp; 
    } 
    return result; 
} 
+0

使用兩個循環?您正在重複測試以找到tmp的最高值,使得'(24 << tmp) MSalters 2009-11-27 13:04:56

+0

對不起,您的算法是當然更快,這是我想到的第一件事。 – 2009-11-27 13:50:29