Java双溢出

时间:2015-11-09 22:43:04

标签: 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) );

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

1 个答案:

答案 0 :(得分:1)

我试过你的表情(因为我不知道 c1 c2 c12 N的来源我硬编码了他们的价值观)。所以硬编码的值看起来像这样:

double c1 = 0.1;
double c2 = 0.2;
double c12 = 0.3;
double N = 0.4;

我有可能= NaN

如上述评论所述,请注意输入。第一个有问题的表达式是(由于额外的小数字或大数字的划分,你可以在这里溢出):

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

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

一般来说,你不仅可以获得溢出(在极端情况下),还可以获得 NaN (即使是“看起来很健康”的输入)。

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