計算floor(log_2(x))
可以通過計算快速算法的零的數量來完成。如何有效地計算樓層日誌庫2 ^(1/4)
是否有任何類似的計算floor(log_{2^(1/4)}(x))
當x
是64位無符號整數範圍內所有可能的值?
由於log_{2^(1/4)}(x)=4*log_2(x)=log_2(x^4)
,這相當於找到floor(4*log_2(x))
或floor(log(x^4))
的高效算法。
計算floor(log_2(x))
可以通過計算快速算法的零的數量來完成。如何有效地計算樓層日誌庫2 ^(1/4)
是否有任何類似的計算floor(log_{2^(1/4)}(x))
當x
是64位無符號整數範圍內所有可能的值?
由於log_{2^(1/4)}(x)=4*log_2(x)=log_2(x^4)
,這相當於找到floor(4*log_2(x))
或floor(log(x^4))
的高效算法。
我們計算floor(log_2(x))
後,我們可以把z = x/2^floor(log_2(x))
並在z
屬於範圍[1, 2)
,因爲floor(log_{2^(1/4)}(x)) = 4 floor(log_2(x)) + floor(log_{2^(1/4)}(z))
考慮計算floor(log_{2^(1/4)}(z))
的問題。只有四種可能性floor(log_{2^(1/4)}(z))
,所以兩個比較(三爲網點)的z
與常量
(2^(1/4))^1, (2^(1/4))^2, (2^(1/4))^3
就足夠了。爲了完全避免浮點運算,可以將「除法」實現爲左移,將(2^63) z
與類似代表的常量進行比較。
#include <assert.h>
#include <stdio.h>
static int mylog(unsigned long long x) {
assert(x > 0ULL);
/* compute n = floor(log2(x)) */
unsigned long long y = x | (x >> 1);
y |= y >> 2;
y |= y >> 4;
y |= y >> 8;
y |= y >> 16;
y |= y >> 32;
y -= (y >> 1) & 0x5555555555555555ULL;
y = (y & 0x3333333333333333ULL) + ((y >> 2) & 0x3333333333333333ULL);
y = (y + (y >> 4)) & 0x0f0f0f0f0f0f0f0fULL;
y = (y + (y >> 8)) & 0x00ff00ff00ff00ffULL;
y = (y + (y >> 16)) & 0x0000ffff0000ffffULL;
y = (y + (y >> 32)) & 0x00000000ffffffffULL;
int n = (int)y - 1;
/* normalize x and use binary search to find the last two bits of the log */
x <<= 63 - n;
n <<= 2;
if (x < 0xb504f333f9de6485ULL) {
return x < 0x9837f0518db8a970ULL ? n : n + 1;
} else {
return x < 0xd744fccad69d6af5ULL ? n + 2 : n + 3;
}
}
int main(void) {
unsigned long long x;
while (scanf("%llu", &x) == 1) {
printf("%d\n", mylog(x));
}
}
的數學/ Wolfram Alpha的查詢來計算常數是
BaseForm[Table[Ceiling[2^(63+i/4)],{i,1,3}],16] .
這是神奇的,謝謝!作爲一個額外的好處,由於大'x'的舍入誤差,這實際上比天真的'floor(4 * log_2(x))'方法更準確。 表現明智,Go的直接翻譯不會產生如我預期的那樣巨大的性能差異。對於隨機的,均勻分佈的uint64值,我將「54.7ns/op」用於幼稚的方法,對於上面的則用「19.8ns/op」。單獨的log_2計算部分在7.9ns/op處進行基準測試。 – Frumple 2014-08-29 13:32:08
LOG_ {2 ^(1/4)}(X)= log_2(X:
與C語言代碼現在)/ log_2(2 ^(1/4))= log_2(x)/(1/4)= 4 log_2(x) – Frumple 2014-08-28 21:11:27
哦,哎呀,我忘了分母中的2 ^。抱歉! – templatetypedef 2014-08-28 21:40:33