2014-08-28 37 views
0

計算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))的高效算法。

+0

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

+0

哦,哎呀,我忘了分母中的2 ^。抱歉! – templatetypedef 2014-08-28 21:40:33

回答

0

我們計算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] . 
+0

這是神奇的,謝謝!作爲一個額外的好處,由於大'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