源我的答案:整數除以7
Is this expression correct in C preprocessor
我一點點我的長處在這裏,我試圖理解這個特定的優化工作。
正如答覆中提到,GCC將通過7優化整數除法:
mov edx, -1840700269
mov eax, edi
imul edx
lea eax, [rdx+rdi]
sar eax, 2
sar edi, 31
sub eax, edi
它轉換回C作爲:
int32_t divideBySeven(int32_t num) {
int32_t temp = ((int64_t)num * -015555555555) >> 32;
temp = (temp + num) >> 2;
return (temp - (num >> 31));
}
讓我們先來看看第一部分:
int32_t temp = ((int64_t)num * -015555555555) >> 32;
爲什麼這個數字?
那麼,讓我們取2^64併除以7,看看彈出了什麼。
2^64/7 = 2635249153387078802.28571428571428571429
這看起來像一團糟,如果我們把它轉換成八進制呢?
0222222222222222222222.22222222222222222222222
這是一個非常漂亮的重複模式,肯定不能是巧合。我的意思是我們記得7是0b111
,我們知道當我們除以99時,我們傾向於獲得基數爲10的重複模式。因此,當我們除以7時,我們將在基數8中得到重複模式。
那麼我們的號碼進來了嗎?
(int32_t)-1840700269
相同(uint_32t)2454267027
* 7 = 17179869189
最後17179869184是2^34
這意味着17179869189爲7 2^34最接近的倍數。或者換一種說法2454267027是,將適合在uint32_t
,當乘以7非常接近的2
什麼是八進制這個數字電源數量最多?
0222222222223
爲什麼這很重要?那麼,我們要除以7.這個數字大約是2^34/7 ...。所以如果我們乘以它,然後移位34次,我們應該得到一個非常接近確切數字的數字。
最後兩行看起來像是爲修補近似誤差而設計的。
也許有人在這方面有更多的知識和/或專業知識可以在這方面作出貢獻。
>>> magic = 2454267027
>>> def div7(a):
... if (int(magic * a >> 34) != a // 7):
... return 0
... return 1
...
>>> for a in xrange(2**31, 2**32):
... if (not div7(a)):
... print "%s fails" % a
...
故障開始在3435973841這是有趣的是0b11001100110011001100110011010001
判斷爲什麼逼近失敗是有點超出我,爲什麼補丁修復它是爲好。有誰知道魔法如何超越我在這裏放下的東西?
http://www.hackersdelight.org/divcMore.pdf – 2013-03-07 03:21:12
該pdf對於確定最後一行是什麼非常有用(標記修復);但是,除非我錯過了它,否則似乎沒有特別討論這種算法。 – OmnipotentEntity 2013-03-07 03:36:41
明確的參考文獻是[here](http://gmplib.org/~tege/divcnst-pldi94。pdf)(在gcc編譯器中實現)和後續[here](http://gmplib.org/~tege/division-paper.pdf)。實現可以在[GMP](http://gmplib.org/)庫中找到。 ('gmp-impl.h'中的'udiv_qrnnd_preinv') – 2013-03-07 08:25:35