在java中除法后,大十进制值的总和应该相等

时间:2017-12-04 09:34:39

标签: java

我有6 BigDecimals,请说

a,b,c,d,e,f and tot 所有这些值(a,b,c,d,e,f)的总和等于tot 我正在计算平均值并存储在BigDecimal类型的其他变量中,只需说avgA, avgB, avgC, avgD, avgE, avgF and avgTot。现在,如果我添加所有这些

avgA, avgB, avgC, avgD, avgE, avgF 

此总和应等于avgTot

但所有平均值(avgA, avgB, avgC, avgD, avgE, avgF)的总和不等于totAvg

这是示例代码

BigDecimal avgA = a.divide(new BigDecimal(counter), 15,RoundingMode.CEILING);
BigDecimal avgB = b.divide(new BigDecimal(counter), 15,RoundingMode.CEILING);
BigDecimal avgTot = tot.divide(new BigDecimal(counter), 15,RoundingMode.CEILING);

BigDecimal trimA = avgA.setScale(4, RoundingMode.CEILING);
BigDecimal trimB = avgB.setScale(4, RoundingMode.CEILING);
BigDecimal trimTot = avgTot.setScale(4, RoundingMode.CEILING);

示例值: -

trimA 0.0004
trimB 0.0000
trimC 0.0022
trimD 0.0047
trimE 0.0000
trimF 0.0002
trimTot 0.0076

问题是sum(TrimA..F)不等于trimTot。我必须确保sum(TrimA..F)应该等于trimTot

2 个答案:

答案 0 :(得分:0)

狡猾的是RoundingMode.CEILING确保添加的最大错误而不是RoundingMode.HALF_UP

CEILING

0.00031 => 0.0004
0.00211 => 0.0022
-------    ------ +
0.00242    0.0026

HALF_UP(标准)

0.00033 => 0.0003
0.00216 => 0.0022
-------    ------ +
0.00249    0.0025

楼层

0.00043 => 0.0004
0.00216 => 0.0021
-------    ------ +
0.00259    0.0025

所以

BigDecimal trimA = avgA.setScale(4, RoundingMode.HALF_UP);
BigDecimal trimB = avgB.setScale(4, RoundingMode.HALF_UP);
BigDecimal trimTot = avgTot.setScale(4, RoundingMode.HALF_UP);

会最小化舍入误差,但不一定总是将其删除。

那么你怎么想,没有四舍五入到四位小数。从15个位置到4个位置。

答案 1 :(得分:0)

通常Round(A + B)= Round(A)+ Round(B)的任何舍入方法都不是这种情况。

人们以高精度提出这些问题,以尽量减少可见舍入错误的发生率但通常不能完全发挥作用。 注意:Joop Eggen刚刚发布了这样的答案。请注意,我没有在评判意义上使用'bodge'!

如果不解释为什么需要一个不可能的约束,就很难给出有用的建议。

一种显而易见的方法是定义 A,B,C的平均值为A / 3 + B / 3 + C / 3。 另一种方法是通过计算作为有理数。 这意味着要么跟踪分子和分母,要么使用专门的Rational class