我们正在计算必须与原始总数相匹配的百分比。但是对于浮点数,总数永远不会匹配。
实施例。
总百分比是从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.");
}
答案 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
}