我正在开发一个项目,它根据这些查询的结果进行大量查询和一些数学建模,最后进行一些评分(读取:“执行时间太长,无法彻底测试”)。
最近我在我的代码中意识到了一个相当新的问题/错误;一些结果得分为NaN
值!以下是分数的计算方法:
请注意,pfound
,psig
为double
,始终为正或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
的可能原因,但我相信大部分原因应该是安全的:
我已经在检查pfound == 0(所以没有除以零)
Math.log()的参数不能为负值
我怀疑factorial()
(一个将阶乘返回为long
的自定义函数)是否返回long
如此之大以至于无法将其转换为{ {1}}不会失去精确度或类似的东西。我检查了double
,如果它的参数导致Long.doubleValue()
,它显然会生成NaN
。
有何评论?我错过了一些基本的东西吗?
答案 0 :(得分:3)
如果你的阶乘正在对x进行天真的评价! = 1 * 2 * 3 ...,我敢打赌,你要求的数字的阶乘不能适合你正在使用的参考。
两条建议:
阶乘(n)的递归,其中n> 12是一个非常糟糕,天真的想法。你没有认真考虑过这样的事情,是吗?
答案 1 :(得分:2)
你不应该明确地将双打与零进行比较 - 它几乎从不起作用。最好做这样的事情:
double EPS = 0.0000001;
if (Math.abs (pfound) < EPS) { //pfound is null }
我看到的唯一可以产生NaN的地方是Math.log
。从其文档:
- 如果参数为NaN或小于零,则结果为NaN。
- 如果参数为正无穷大,则结果为正 无穷大。
- 如果参数为正零或负零,则结果为 负无穷大。
醇>
我认为pfound
包含负值零,这就是你获得NaN的原因。尝试在调试器中跟踪变量值。
答案 2 :(得分:2)
NaNs通过各种算术运算传播,所以即使你正确地检查这里的条件,它们也可以从其他地方引入。
我怀疑是alpha_coeff [0]还是pfound - 尝试检查这些是否为NaN。
NaN也可能是您的阶乘函数的结果,具体取决于它的定义方式。编辑:刚刚注意到你指定这会产生一个长的,因此因子不能产生NaN,另一方面,如果它溢出会导致来自log()的NaN,它会产生负面结果。