在Java中,我希望0.101d,0.109999999d和0.11000d在功能上都相同。我试图使用BigDecimal和一个具有2位精度的MathContext和RoundingMode.CEILING来做到这一点,但我的单位测试显示0.11000轮到0.12。我希望0.110000d回合到0.11。
private static MathContext targetMathContext = new MathContext(2, RoundingMode.CEILING);
public static double roundedTarget(double d) {
BigDecimal bd = new BigDecimal(d,targetMathContext);
return bd.doubleValue();
}
JUnit:
double c = 0.445d;
double s = 0.5d;
double p = (s-c)/s; // 0.1099999..... in dfp
double rgpp = roundedTarget(p); // 0.11
double rgppp = roundedTarget(rgpp); // 0.12
// operation is not idempotent as f(x) != f(f(x)) :(
Assert.assertEquals("These values should be equal",rgpp,rgppp);
解决方案:
public static double roundedTarget(double d) {
return BigDecimal.valueOf(d)
.setScale(2,BigDecimal.ROUND_CEILING)
.doubleValue();
}
答案 0 :(得分:2)
我不愿意将此操作称为幂等,因为您的第一个函数应用程序的输入将与下一个不同(因为您获得的结果将更改x
的值)。 / p>
在任何一种情况下,主要问题是您在一个地方使用双打(并引入浮点不准确),而在另一个地方使用BigDecimal
(如果使用正确,则受这些不准确性的影响较小)
最简单要做的事情是在你的双打上设置2个小数位的比例,然后根据你喜欢的方式对它们进行舍入。例如,所有这些值都满足您在评论中提到的条件。
BigDecimal firstDecimal = BigDecimal.valueOf(0.101).setScale(2, RoundingMode.CEILING);
BigDecimal secondDecimal = BigDecimal.valueOf(0.10999).setScale(2, RoundingMode.CEILING);
BigDecimal thirdDecimal = BigDecimal.valueOf(0.110000).setScale(2, RoundingMode.CEILING);
BigDecimal fourthDecimal = BigDecimal.valueOf(0.1101).setScale(2, RoundingMode.CEILING);
System.out.println(firstDecimal); // 0.11
System.out.println(secondDecimal); // 0.11
System.out.println(thirdDecimal); // 0.11
System.out.println(fourthDecimal); // 0.12
这里的主要内容是:如果您要使用BigDecimal
,始终与之保持一致。没有真正的理由进行交织或交织工作使用原始双打和BigDecimal
,因为它只会导致像这样的头痛。