【问题标题】:Avoid floating point precision issue using java.math.BigDecimal使用 java.math.BigDecimal 避免浮点精度问题
【发布时间】:2016-12-01 03:00:50
【问题描述】:

我有一个由双值(从 0 到 1)填充的矩阵。为方便起见,让我们谈谈行和列。我想规范化矩阵的双精度值,以便每一列的所有行的总和返回 1。此任务触发浮点精度问题,因为使用 double,总和将永远不会返回 1。 所以我尝试使用BigDecimal,但结果略有不同。

这是我的代码:

    double[][] U = new double[6][1015];
    double[] sumPerCol = new double[db.size()+1];
    for(int i=0; i<U.length; i++){
        for(int j =0; j<U[i].length; j++){
            double x = new Random().nextDouble();
            U[i][j] = x;
            sumPerCol[j] += x;
        }
    }
    double[] sumPerCol2 = new double[db.size()+1];
    for(int i=0; i<U.length; i++){
        for(int j =0; j<U[i].length; j++){
            BigDecimal x = new BigDecimal(U[i][j],MathContext.DECIMAL128);
            BigDecimal tot = new BigDecimal(sumPerCol[j],MathContext.DECIMAL128);
            BigDecimal x2 = x.divide(tot,MathContext.DECIMAL128);
            U[i][j] = x2.floatValue();
            sumPerCol2[j] += U[i][j];
        }
    }
    for(double d : sumPerCol2){
        System.out.println(d);
    }

当然,我没有正确使用BigDecimal。有人可以帮忙吗?

【问题讨论】:

  • 如果你真的想要精度,你可以使用 BigDecimal,但不要将它们与双精度数混合。但即使是 BigDecimal,除法也不能总是产生精确的结果。

标签: java precision bigdecimal


【解决方案1】:

您是对的,您不能安全地对双精度值使用 ==。但你可能不需要那个。对矩阵进行归一化只需要将每个元素除以相应列元素的总和。如果要检查归一化,只需对元素求和并检查与 1 的差异是否“非常小”(您可以定义一个 epsilon 值,例如 10^(-10)。

我看不出有什么理由在这里使用 BigDecimal。如果出于某种原因,您确实需要绝对精度,请使用有理数(分数)的适当实现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-12
    • 2012-09-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多