Java中的数学问题; uncanny NaN来自计算

时间:2010-07-06 15:27:18

标签: java math logarithm

我正在开发一个项目,它根据这些查询的结果进行大量查询和一些数学建模,最后进行一些评分(读取:“执行时间太长,无法彻底测试”)。

最近我在我的代码中意识到了一个相当新的问题/错误;一些结果得分为NaN值!以下是分数的计算方法:

请注意,pfoundpsigdouble,始终为正或0

Double  score1 = (pfound!=0) ? (Math.log(factorial((int)psig + 1))/pfound) : 0;

score1 = score1 * alpha_coeff[0];
if (score1.isInfinite())
    throw new RuntimeException(p.getName() + " score1 = Inf");
else if(score1.isNaN())
    throw new RuntimeException(p.getName() + " score1 = NaN");

我已检查触发NaN的可能原因,但我相信大部分原因应该是安全的:

  1. 我已经在检查pfound == 0(所以没有除以零)

  2. Math.log()的参数不能为负值

  3. 我怀疑factorial()(一个将阶乘返回为long的自定义函数)是否返回long如此之大以至于无法将其转换为{ {1}}不会失去精确度或类似的东西。我检查了double,如果它的参数导致Long.doubleValue(),它显然会生成NaN

    有何评论?我错过了一些基本的东西吗?

3 个答案:

答案 0 :(得分:3)

如果你的阶乘正在对x进行天真的评价! = 1 * 2 * 3 ...,我敢打赌,你要求的数字的阶乘不能适合你正在使用的参考。

两条建议:

  1. 如果是这样的话,请尝试BigDecimal
  2. 使用gamma function代替天真实施。
  3. 阶乘(n)的递归,其中n> 12是一个非常糟糕,天真的想法。你没有认真考虑过这样的事情,是吗?

答案 1 :(得分:2)

你不应该明确地将双打与零进行比较 - 它几乎从不起作用。最好做这样的事情:

double EPS = 0.0000001;
if (Math.abs (pfound) < EPS) { //pfound is null } 

我看到的唯一可以产生NaN的地方是Math.log。从其文档:

  
      
  1. 如果参数为NaN或小于零,则结果为NaN。
  2.   
  3. 如果参数为正无穷大,则结果为正   无穷大。
  4.   
  5. 如果参数为正零或负零,则结果为   负无穷大。
  6.   

我认为pfound包含负值零,这就是你获得NaN的原因。尝试在调试器中跟踪变量值。

答案 2 :(得分:2)

NaNs通过各种算术运算传播,所以即使你正确地检查这里的条件,它们也可以从其他地方引入。

我怀疑是alpha_coeff [0]还是pfound - 尝试检查这些是否为NaN。

NaN也可能是您的阶乘函数的结果,具体取决于它的定义方式。编辑:刚刚注意到你指定这会产生一个长的,因此因子不能产生NaN,另一方面,如果它溢出会导致来自log()的NaN,它会产生负面结果。