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