[英]Need help in translating code from C to Java
從這個文章。 這是代碼:
float InvSqrt(float x){ // line 0
float xhalf = 0.5f * x;
int i = *(int*)&x; // store floating-point bits in integer
i = 0x5f3759d5 - (i >> 1); // initial guess for Newton's method
x = *(float*)&i; // convert new bits into float
x = x*(1.5f - xhalf*x*x); // One round of Newton's method
return x;
}
...我什至不知道這是C還是C ++。 [好吧,顯然是C,謝謝]有人可以幫我把它翻譯成Java嗎? 是(僅,我希望)第2行和第4行使我感到困惑。
您要使用以下方法:
而且strictfp
等可能存在問題。
大概是這樣的:(注意:未經測試!)
float InvSqrt(float x){ // line 0
float xhalf = 0.5f * x;
int i = Float.floatToIntBits(x); // store floating-point bits in integer
i = 0x5f3759d5 - (i >> 1); // initial guess for Newton's method
x = Float.intBitsToFloat(i); // convert new bits into float
x = x*(1.5f - xhalf*x*x); // One round of Newton's method
return x;
}
這些行用於在float
和int
之間轉換為位模式。 Java在java.lang.Float
具有靜態方法,其他方法都是相同的。
static float InvSqrt(float x) { // line 0
float xhalf = 0.5f * x;
int i = Float.floatToIntBits(x); // store floating-point bits in integer
i = 0x5f3759d5 - (i >> 1); // initial guess for Newton's method
x = Float.intBitsToFloat(i); // convert new bits into float
x = x * (1.5f - xhalf * x * x); // One round of Newton's method
return x;
}
您引用的代碼是C,盡管注釋是C ++樣式的。
代碼正在執行的操作涉及在位級別上存儲浮點值的方式的知識。 “幻數” 0x5f3759d5
與特定值有關。
初始化i
時將訪問浮點x
值的位,因為x
的地址已取消引用。 因此, i
加載了浮點值的前32位。 在下一行, x
寫入i
的內容,從而更新工作近似值。
我已經讀到,當約翰·卡馬克(John Carmack)與Id的開源Quake引擎一起發布該代碼時,它變得很流行。 該代碼的目的是快速計算1 / Sqrt(x),該值用於圖形引擎的光照計算。
我將無法直接將此代碼轉換為Java,因為它使用了如上所述的“類型校正”(當它像訪問int一樣訪問內存中的float時)。 Java阻止了這種活動,但是正如其他人指出的那樣,Float對象提供了圍繞它的方法。
在C中使用這種奇怪的實現的目的是為了使其非常快。 在撰寫本文時,我想這種方法會帶來很大的改進。 我不知道當浮點運算變得更快時,今天的差異是否值得。
使用Java方法將float轉換為整數位並返回,可能比直接使用Java數學函數求平方根簡單地計算平方根的倒數要慢。
好的,我在這里走了一步,因為我知道C,但是我不懂Java。
從字面上看,用Java重寫此C代碼很麻煩。 即使在C語言中,代碼也是不可移植的。 它依賴於其他因素:浮點數的大小。 整數的大小。 浮點數的內部表示。 浮點數和整數的字節對齊。 右移(即i >> 1)是使用邏輯右移實現的,而與算術右移相反(算術右移會在具有高階1位的整數上移1,因此不再等於2)。
我了解Java會編譯為字節碼,而不是直接編譯為機器碼。 字節碼解釋器的實現者使用基於字節碼規范的假設進行調整,並理解編譯器從明智的輸入源代碼輸出的內容。
這樣的黑客不屬於“明智的輸入來源”。
沒有理由期望解釋器會隨着您的C hack的執行而更快,實際上,很有可能它會變慢。
我的建議是:IGNORE C代碼。
尋找以Java為中心的效率提升。
C hack的概念是:
利用已知的浮點數的內部表示已經打破了指數的認識,近似為1 / square(x),如果您已經有了exponent(x),exponent(x)/ 2的計算比root(x)更快。 )。
然后,hack將執行牛頓方法的一次迭代,以減少近似誤差。 我假設一次迭代將錯誤減少到可以容忍的程度。
也許該概念值得用Java進行研究,但是細節將取決於對JAVA如何實現的深入了解,而不是C的實現方式。
您關心的行非常簡單。 第2行采用float x
的字節,它們以某種浮點表示形式(如IEEE754)存儲在整數中,與它們的存儲方式完全相同。 這將導致完全不同的數字,因為整數和浮點數以字節形式表示的方式有所不同。 第4行做相反的事情,然后將int中的字節再次傳輸到float
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.