1

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

例子。

总百分比从 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.81 相比减少了 1 美分 327.80

最后,我需要验证这两个金额是否相等——这显然不会验证。管理层告诉我要在我的逻辑中添加 0.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.");
}
4

2 回答 2

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());
}
于 2012-10-24T19:08:30.693 回答
1
final double EPSILON = 0.05;
double a = 0.5;
double b = 0.51;
if (Math.abs(a-b) <= EPSILON){
// match
}
else{
// no match
}
于 2012-10-24T19:16:59.757 回答