在bigdecimal比较中创建5分方差+

时间:2012-10-24 18:56:33

标签: java

我们正在计算必须与原始总数相匹配的百分比。但是对于浮点数,总数永远不会匹配。

实施例。

总百分比是从327.81

计算的

非舍入金额的示例

30%     98.343
20%     65.562
30%     98.343
20%     65.562
Total  327.81 

舍入金额的示例

30% 98.34
20% 65.56
30% 98.34
20% 65.56
Total 327.80 

我的金额需要四舍五入为货币格式,但是您会注意到舍入金额比327.80低了1美分,等于我们原来的327.81

最后,我需要验证这两个数量是否相等 - 显然不会验证。管理层告诉我,我的逻辑添加了.05方差。我能够比较彼此相等的值,但是我不确定如何将方差添加到等式中。有人可以帮我弄清楚如何将其添加到我的状态。

这是我当前的代码,比较它们彼此相等。

if (   this.pr.getRequisitionTotal() != null 
    && this.pr.getRequisitionTotal().compareTo(lineItemTotal) != 0
    && this.reviewedAuditActions()) 
{
    this.form.recordError("Requisition total must equal line item running total.");
}

2 个答案:

答案 0 :(得分:1)

标准解决方案是跟踪“实际”金额和圆形版本之间的累积偏差,并调整舍入以保持偏差小于0.5。这是使用BigDecimal的概念的实现,这使得它有点罗嗦但是如果使用浮点则避免表示问题。

如果您创建了一个名为RoundingAccumulator的类来封装此行为,则可以隐藏其余代码中的杂乱细节。

    BigDecimal value = new BigDecimal("327.81");
    BigDecimal[] percents = new BigDecimal[] {
            new BigDecimal(30),
            new BigDecimal(20),
            new BigDecimal(30),
            new BigDecimal(20) };
    BigDecimal accError = BigDecimal.ZERO;
    BigDecimal maxError = new BigDecimal("0.005");
    BigDecimal adjust   = new BigDecimal("0.01");
    BigDecimal hundred  = new BigDecimal("100");
    BigDecimal total    = BigDecimal.ZERO;
    for (BigDecimal pct : percents)
    {
        BigDecimal unrounded    = value.multiply(pct).divide(hundred); 
        BigDecimal rounded      = unrounded.setScale(2,RoundingMode.HALF_EVEN);
        BigDecimal error        = rounded.subtract(unrounded);
        BigDecimal correction   = BigDecimal.ZERO;
        accError = accError.add(error);
        if (accError.abs().compareTo(maxError) > 0)
            correction = accError.signum() > 0 ? adjust.negate() : adjust;
        rounded = rounded.add(correction);
        accError = accError.add(correction);
        System.out.println(unrounded.toString() + " " + rounded.toString() + " " + error.toString() + " " + accError.toString() + " " + correction.toString());

        total = total.add(rounded);
    }
    System.out.println("Total is " + total.toString());
}

答案 1 :(得分:1)

final double EPSILON = 0.05;
double a = 0.5;
double b = 0.51;
if (Math.abs(a-b) <= EPSILON){
// match
}
else{
// no match
}