Java双溢出

Java双溢出,java,double,overflow,bigdecimal,Java,Double,Overflow,Bigdecimal,所以基本上,我试图计算两件事同时发生的可能性比。 这些方程式很简单,但问题是我的数据相当大,有时中间的运算会溢出 我目前正在对变量使用double,因此无法进行上转换。 此外,该方程具有对数和指数运算符。但是,我没有找到任何用于BigDecimal或类似类型的非基本数学函数 此外,我已经尽可能地简化了方程 我想知道我的选择是什么。这是我的密码: c1 = unigramsInfo.get(w1)[0]; c2 = unigramsInfo.get(w2)[0]; c12

所以基本上,我试图计算两件事同时发生的可能性比。
这些方程式很简单,但问题是我的数据相当大,有时中间的运算会溢出

我目前正在对变量使用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。

我试过你的表达式(因为我不知道c1c2c12N的起源,我硬编码了它们的值)。因此,硬编码值如下所示:

double c1 = 0.1;
double c2 = 0.2;
double c12 = 0.3;
double N = 0.4;
我得到了可能性=NaN

如上所述,注意输入。第一个有问题的表达式是(由于额外的小数字或大数字被除法,这里可能会出现溢出):

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

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


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

也许您需要“有时中间操作溢出”。以防您有无效输入。值永远不应该那么大。你能给出一个实际的例子吗?注:1e-7不会导致double溢出。溢出发生在哪里?
p1=c12/c1
将溢出为
c1==0
,必须作为特殊情况处理。另外,
c1==N
也会触发溢出。@PeterLawrey谢谢你的评论。我仔细考虑了这个问题,因为我只检查了“p”而不是其他概率。在这里,似乎有时会发生‘c12==c1’和‘c12==c2’,这就是破坏方程的原因。
double p = c2 / N;
double p1 = c12 / c1;
double p2 = (c2 - c12) / (N - c1);