2

我想計算(1.0-p)^n其中p是0到1之間的一個雙精度值(通常非常接近0),n是一個正整數,可能大約爲數百或數千(也許更大;我還不確定)。如果可能的話,我希望僅僅使用java.lang.Math.pow(1.0-p, n)中的Java構建這個,但是我略微擔心,在我感興趣的值的範圍內,可能會有巨大的準確性/精確度損失。是否有人有一個關於使用Java的實現可能會出現什麼樣的錯誤的粗略想法?我不確定它們的實現(日誌和/或泰勒近似值)背後發生了什麼,所以我不能冒險一個好猜測。對於大n,java.lang.Math.pow(x,n)的準確性/精確性如何?

我最關心的是相對誤差(即不超過一個數量級)。如果答案結果是Java的實現會產生太多的錯誤,那麼您是否有任何好的庫建議(但是我希望這不再需要)?謝謝。

回答

4

According to the API doc:

計算結果必須是內準確結果的1 ulp。

所以我認爲你不需要擔心如何實現浮點精度的限制。如果準確性而不是性能是您最關心的問題,您可能需要考慮使用BigDecimal.pow()

+0

找到我實際上檢查過Javadoc,但我不知何故錯過了這一行,謝謝。至於'BigDecimal',在我意識到'n'是一個整數之前,我已經排除了這一點。我認爲這也會起作用。 – 2011-04-05 21:35:55

0

你可以看看java.land.Math類的源文件,看看你能否理解確切的方法。這裏是鏈接,http://www.docjar.com/html/api/java/lang/Math.java.html

+0

我嘗試過,但最終訴諸本地代碼,我不知道從那裏去哪裏。 – 2011-04-05 21:25:39

+0

您如何嘗試使用Java StrictMath類 - http://download.oracle.com/javase/1.4.2/docs/api/java/lang/StrictMath.html。我相信這些算法在文檔中定義得更好(或者至少命名所使用的alg以便查找它)。 – Zorayr 2011-04-06 22:40:25

+0

@Michael McGowan本地java.lang.Math代碼的實現可以在ftp://ftp.netlib.org/fdlibm.tar – Christopher 2011-07-21 05:33:55

0

一些實證結果:

public static void main(String[] args) 
{ 
    double e = 0.000000000001d; 
    System.out.println(Math.pow(1-e, 1.0d/e)); 
    float f = 0.000001f; 
    System.out.println(Math.pow(1-f, 1.0f/f)); 
} 

0.36788757938730976 
0.3630264891374932 

雙方應當收斂到1/e(0.36787944 ....)所以很明顯浮動是不可能的,但雙可能有足夠的精度爲您服務。

+2

這不是測量'pow()'的精確度;它正在測量評估包含'pow()'的表達式以及浮點表示,減法和除法的表達式的準確性。即使pow()完全準確,這個計算的結果也不會精確地等於1/e(這個表達式的值也不會等於1/e,因爲當以「理想」浮點運算)。 – 2011-04-05 21:58:46