问题描述
我想获得具有以下属性的 BigDecimal 值:
- 舍入模式:半偶
- 点后的位数:2
我有以下代码:
public BigDecimal standardDeviation() {
MathContext mc = new MathContext (4,RoundingMode.HALF_EVEN);
return new BigDecimal(Math.sqrt(variance().doubleValue()),mc);
}
在测试时,当我发送一些值时,出现以下故障:
invalid standard deviation ==> expected: <16.73> but was: <16.72>
我该如何解决这个问题?
解决方法
总结评论:
invalid standard deviation ==> expected: <16.73> but was: <16.72>
请注意,您很可能对此处的舍入模式有误解。
注意 HALF_EVEN 上的 JavaDoc:
“如果舍弃分数左边的数字是奇数,则行为与 RoundingMode.HALF_UP 相同;如果是偶数,则行为与 RoundingMode.HALF_DOWN 相同”
这意味着像 16.725 这样的数字将被四舍五入而不是向上舍入,因此使用 HALF_EVEN 的结果将是 16.72。
如何将 95 (BigDecimal) 转换为 95.00 ?
从数字的角度来看,95 和 95.00 之间没有区别,因为尾随零与前导零一样无关紧要。从这个意义上说,即使 0095.0000 也是相同的数值。
当您处理 BigDecimal 时,您的第一个目标通常是进行计算,因此不会受到“任意”精度问题影响的数值(不支持不确定精度,但可以将其设置为固定值)并且尽可能准确。
因此,如果您从数字 95、95.0 甚至字符串“95.00”创建一个 BigDecimal,它们将具有相同的值。
然而,它们并不相等,因为数字在内部也有一个刻度,即 95 和 95.0 通常在内部表示为整数 95 和 0,这意味着小数点不必移动。另一方面,"95.00"
将表示为数字 9500 和比例为 2,这意味着要获得实际数字,您需要将小数点向左移动 2 位数字。
话虽如此,如果您想检查 BigDecimals 是否相等,请不要使用 equals()
,因为这也考虑了比例,但请使用 compareTo() == 0
,因为它只会比较数值。
我正在开发一个支付系统,即使数字像 95,我也需要返回带有 2 位数字的数字。
一般来说,这更多是格式问题。只要计算正确完成,您的系统用户就不会关心内部有多少小数位数。当您需要向用户显示一个数字时,您需要将其转换为字符串,这就是格式设置的用武之地。
要生成格式良好的字符串,您可以使用任何基于 java.utilFormatter
的方法,例如String.format(printf("%.2f",bigDecimal);
最后,有一种方法可以将 BigDecimal.toString()
的输出实际更改为 95.00,但我不建议为此目的使用它:尝试 new BigDecimal(95).setScale(2).toString()
。 >
相反,将输出格式化为您需要的小数位数,并使用 setScale()
之类的方法仅正确舍入,例如如果您想四舍五入为 2 个小数位,请尝试 new BigDecimal(16.725).setScale(2,RoundingMode.HALF_UP)