Java 双重溢出

标签 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。

最佳答案

我试过你的表达方式(因为我不知道 c1c2c12N 的来源 我硬编码了他们的值(value)观)。所以硬编码值看起来像这样:

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

我有 likelihood=NaN

如上评论所述,注意输入。第一个有问题的表达式是(由于额外的小数或大数的除法,您可能会在此处溢出):

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

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

一般来说,您不仅会出现溢出(在极端情况下),还会出现 NaN(即使是“看起来很正常”的输入)。

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

关于Java 双重溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33619725/

相关文章:

java - 将Spring Boot与Elastic搜索集成的最佳方法

swift - 计算参数的平均值

css - webkit 滚动条上的不同宽度

c++ - 什么会导致 Phong 镜面反射着色产生色域溢出?

html - 如何使图像从容器底部开始?

java - 找不到 ID 为 'gwt' 的插件

java - Spring 启动 2 : Unable to build Hibernate SessionFactory

java - 从另一个程序触发java程序会使用相同的JVM还是会使用不同的JVM?

Java - double*int 算术显示两位小数或几个小数位

c - 链接 c 文件时覆盖变量