2

我正在做一个项目,该项目基于这些查询的结果进行大量查询和一些数学建模,最后是一些评分(阅读:“执行时间太长而无法彻底测试”)。

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

请注意pfoundpsigdouble始终为正或 0 的 s

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() 的参数不能为负值

我怀疑的是factorial()(将阶乘返回为 a 的自定义函数long)是否返回 along太大以至于不能在double不损失精度或类似情况的情况下将其转换为 a 。我检查了Long.doubleValue()NaN如果它的参数导致它显然会生成NaN.

任何意见?我在这里错过了一些基本的东西吗?

4

3 回答 3

3

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

两条忠告:

  1. 如果是这种情况,请尝试 BigDecimal
  2. 使用gamma 函数而不是简单的实现。

n > 12 的阶乘(n)的递归是一个非常糟糕、幼稚的想法。你并没有认真考虑过这样的事情,是吗?

于 2010-07-06T17:43:17.777 回答
2

你不应该明确地将双打与零进行比较——它几乎永远不会奏效。最好做这样的事情:

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

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

  1. 如果参数为 NaN 或小于零,则结果为 NaN。
  2. 如果参数是正无穷大,那么结果是正无穷大。
  3. 如果参数为正零或负零,则结果为负无穷大。

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

于 2010-07-06T15:33:28.273 回答
2

NaN 通过各种算术运算传播,因此即使您正确检查此处的条件,它们也可能是从其他地方引入的。

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

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

于 2010-07-06T15:39:30.163 回答