2014-03-12 92 views
1

我只是試圖將我在C/C++中編寫的以下方法轉換爲Java。簡而言之,代碼提供了一種非常有效的方法來計算數字的最左側和最右側位的索引,這些位設置爲1。這兩種方法都基於代碼的計算機編程的Knuth的藝術,體積4是否有可能獲得雙倍內存中的原始位?

// Returns index of the left-most bit of x that is one in the binary 
// expansion of x. Assumes x > 0 since otherwise lambda(x) is undefined. 
// Can be used to calculate floor(log(x, 2)), the number of binary digits 
// of x, minus one. 
int lambda(unsigned long x) { 
    double y = (double) x; 
    // Excuse the monstrocity below. I need to have a long that has the raw 
    // bits of x in data. Simply (long)y would yield x back since C would cast 
    // the double to a long. So we need to cast it to a (void *) so that C 
    // "forgets" what kind of data we are dealing with, and then cast it to 
    // long. 
    unsigned long xx = *((long *)((void*)&y)); 
    // The first 52 bits are the the significant. The rest are the sign and 
    // exponent. Since the number is assumed to be positive, we don't have to 
    // worry about the sign bit being 1 and can simply extract the exponent by 
    // shifting right 52 bits. The exponent is in "excess-1023" format so we 
    // must subtract 1023 after. 
    return (int)(xx >> 52) - 1023; 
} 


// Returns the index of the right-most one bit in the binary expansion of x 
int rho(unsigned long x) { 
    return lambda(x & -x); 
} 

正如你所看到的,我需要有一個長期具有雙重的同位,但沒有void*投,我不確定如何在Java中執行此操作。有什麼想法嗎?它甚至有可能嗎?

+1

請注意,您開始使用的「C/C++」代碼不起作用:它會打破嚴格的別名規則,即使中間轉換爲void *也是如此。只有大多數編譯器根據程序員的意圖生成代碼。在C中,'memcpy()'或聯合是訪問表示的合適方式。 –

回答

2

有一個靜態函數doubleToLongBits()來執行類型轉換。

long xx = Double.doubleToLongBits(y); 
return (int) (xx >>> 52) - 1023; 

注意>>>將右對齊時的無符號值視爲long。

閱讀評論,不過,這聽起來像你想要的是的number of leading zeros.

return 63 - Long.numberOfLeadingZeros(x); 

我猜想,這是大多數目前的架構更有效率的一個簡單的功能,但你不得不簡介它爲了確定。有一個類似的「尾隨零」方法來計算你的rho()函數。

相關問題