Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 概率极小的准确度_Java_Math_Probability - Fatal编程技术网

Java 概率极小的准确度

Java 概率极小的准确度,java,math,probability,Java,Math,Probability,我用Java编写了一个程序,需要计算一些概率,对于较大的输入,概率最终可能会变得非常小。因此,为了防止下溢问题,我想采用对数概率 然而,我在实现这一点上遇到了困难。在计算的每个阶段,可能会有不同数量的选项,概率需要分配给这些选项,每个阶段的概率加起来需要为1。概率基于许多不同的变量。我使用以下公式计算所有可能性的总和: Math.pow(d[i], a) * Math.pow(1/c[i], b) 这给了我一个变量,total。然后建立概率p_i p_i = (Math.pow(d[i], a

我用Java编写了一个程序,需要计算一些概率,对于较大的输入,概率最终可能会变得非常小。因此,为了防止下溢问题,我想采用对数概率

然而,我在实现这一点上遇到了困难。在计算的每个阶段,可能会有不同数量的选项,概率需要分配给这些选项,每个阶段的概率加起来需要为1。概率基于许多不同的变量。我使用以下公式计算所有可能性的总和:

Math.pow(d[i], a) * Math.pow(1/c[i], b)
这给了我一个变量,
total
。然后建立概率p_i

p_i = (Math.pow(d[i], a) * Math.pow(1/c[i], b)) / total

我的问题是,我如何使用对数概率来实现这一点,这样我就不会得到“无穷大”和“NaN”值,因为到目前为止,我已经得到了这些值。

我认为您应该尝试使用。它将允许正确求和,而不会失去精度

在一些类似C的伪代码中(对不起,我的Java已经生锈,代码未经测试)


不要认为一个和的日志可以简化,那么,这是不是说在这里实现日志概率是不可能的?为什么不使用BigDecimal?您可能需要切换到使用BigDecimal,因为它允许任意精度。我的倾向是您将不得不使用
BigDecimal
,但不幸的是,我想你必须用
BigDecimal
对函数进行对数运算。令人惊讶的是,这不是内置的。。。
double total(int N, double[] d, double[] c, double a, double b) {

    double sum           = 0.0;
    double running_error = 0.0;

    for (int i = 0; i != N; ++i) {
        if (d[i] == 0.0)
            continue;

        if (c[i] == 0.0)
            throw "XXX"; // some error reporting

        double v = 0.0;
        if (d[i] > 0.0 && c[i] > 0.0) {
            // using log trick, if you want
            double lpi = a*Math.log(d[i]) - b*Math.log(c[i]);
            v = Math.exp(lpi);   
        }
        else {
            v = Math.pow(d[i], a) * Math.pow(1.0/c[i], b);
        }

        double difference = v - running_error;
        double temp = sum + difference;
        running_error = (temp - sum) - difference;
        sum = temp;
     }
     return sum;
}