Java 中的数学问题;计算得出的不可思议的 NaN
我正在开发一个项目,该项目进行大量查询,并根据这些查询的结果进行一些数学建模,最后进行一些评分(阅读:“执行时间太长,无法彻底测试”)。
最近我在我的代码中意识到了一个相当新的问题/错误;一些结果的分数为 NaN
值!以下是分数的计算方式:
请注意,pfound
、psig
是始终为正数或 0 的 double
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");
我已经检查了触发<的可能原因code>NaN,但我相信它对于大多数情况应该是安全的:
我已经在检查 pfound == 0 (所以不被零除)
Math.log() 的参数不能有负值
我怀疑是否 Factorial()
(以 long
形式返回阶乘的自定义函数)返回的 long
太大,无法转换为 double
不会损失精度或类似的东西。我检查了 Long.doubleValue(),如果参数结果为 NaN,显然它会生成 NaN。
有什么意见吗?我在这里错过了一些基本的东西吗?
I am working on a project that does a lot of querying and the some mathematical modeling based on results from these queries, and finally some scoring (read: "execution time too long to test thoroughly").
Recently I have realized a rather new problem/bug in my code; some of the results get NaN
values for score! Here's how the scores are calculated:
Note that pfound
, psig
are double
s that are always positive or 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");
I have checked the possible causes triggering NaN
, but I believe it should be safe from most of those:
I am already checking for pfound == 0 (so no divide by zero)
Argument to Math.log() cannot have a negative value
What I suspect is whether or not factorial()
(a custom function which return the factorial as a long
) returns a long
so big that it can't be cast into a double
without loss of precision or something like that. I checked Long.doubleValue()
, and apparently it generates NaN
if it's argument results in NaN
.
Any comments? Am I missing something fundamental here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果你的阶乘正在做 x 的幼稚评估! = 1*2*3...,我敢打赌您要求的是一个不适合您正在使用的参考的数字的阶乘。
两条建议:
阶乘 (n) 的递归,其中 n > 12是一个非常糟糕、天真的想法。你并没有认真考虑过这样的事情,是吗?
If your factorial is doing the naive evaluation of x! = 1*2*3..., I'll bet you're asking for a factorial of a number that can't fit into the reference you're using.
Two pieces of advice:
Recursion for factorial(n) where n > 12 is a very bad, naive idea. You weren't seriously thinking about going forward with something like this, were you?
NaN 通过各种算术运算传播,因此即使您正确检查此处的条件,它们也可能是从其他地方引入的。
我怀疑 alpha_coeff[0] 或 pfound - 尝试检查这些是否为 NaN。
NaN 也可能是阶乘函数的结果,具体取决于其定义方式。编辑:刚刚注意到您指定这会产生一个 long,因此阶乘不能产生 NaN,另一方面,如果它溢出,它可能会产生负结果,这会导致 log() 产生 NaN。
NaNs propagate through various arithmetic operations so even if you are checking the conditions here correctly they could be getting introduced from elsewhere.
I'd suspect either alpha_coeff[0] or pfound - try checking these for NaN.
NaN could also be a result from your factorial function, depending on how this is defined. EDIT: just noticed that you specified that this produces a long, so factorial can't produce a NaN, on the other hand it could produce a negative result if it overflows which would cause a NaN from the log().
您不应该明确地将双精度数与零进行比较 - 它几乎永远不会起作用。最好做这样的事情:
我看到唯一可以产生 NaN 的地方是 Math.log。从它的文档来看:
我认为
pfound
包含接近零的负值,这就是你得到 NaN 的原因。尝试在调试器中跟踪变量值。You shouldn't compare doubles against zero explicitly - it almost never works. Better do something like this:
The only place I see which can produce NaN is
Math.log
. From its documentation:I think
pfound
contains negative value neer zero and that's why you get NaN. Try to track variable values in a debugger.