Java双溢出

Ato*_*pat 5 java double overflow bigdecimal

所以基本上,我试图计算两件事发生在一起的似然比.方程式足够直,但问题是我的数据相当大,有时中间操作溢出.

我目前正在为我的变量使用double,因此无法进行向上转换.
该方程还有对数指数算子.但是我没有找到BigDecimal或类似类型的任何非基本数学函数.

另外,我已经尝试过尽可能地简化方程式.

我想知道我的选择是什么.这是我的代码:

    c1 = unigramsInfo.get(w1)[0];
    c2 = unigramsInfo.get(w2)[0];
    c12 = entry.getValue()[0];
    N = additionalInfo.get("tail")[1];

    p = c2 / N;
    p1 = c12 / c1;
    p2 = (c2 - c12) / (N - c1);

likelihood = - 2 * ( c2 * Math.log(p) + (N - c2) * Math.log(1 - p)
             - c12 * Math.log(p1) - (c1 - c12) * Math.log(1 - p1)
             - (c2 - c12) * Math.log(p2) 
             - (N - c1 - c2 - c12) * Math.log(1 - p2) );
Run Code Online (Sandbox Code Playgroud)

这里的N可能高达一千万,概率可能会小到1.0E-7.

fla*_*z14 1

我已经尝试过你的表达(因为我不知道c1c2c12N的起源,所以我硬编码了它们的值)。所以硬编码值看起来像这样:

double c1 = 0.1;
double c2 = 0.2;
double c12 = 0.3;
double N = 0.4;
Run Code Online (Sandbox Code Playgroud)

我有可能性= NaN

正如上面评论中提到的,注意输入。第一个有问题的表达式是(由于额外的小数或大数的除法,您可能会在这里溢出):

double p = c2 / N;
double p1 = c12 / c1;
double p2 = (c2 - c12) / (N - c1);
Run Code Online (Sandbox Code Playgroud)

然后计算对数。实际上,在我的例子中(上面列出了硬编码值),我在表达式中得到了NaNMath.log(1 - p1)(因为它试图计算负数的十进制对数 - p1 < 1c1 > c2 - 非常可能的情况)。

一般来说,您不仅可以获得溢出(在极端情况下),还可以获得NaN(即使对于“看起来正常”的输入)。

建议将长表达式拆分为小的 Java 表达式。并在计算前验证每个可能导致NaN或溢出的值并手动抛出异常。当您收到无效输入时,这将有助于定位问题的原因。