如何获得 BigDecimal 中的确切值?

问题描述

我想获得具有以下属性的 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)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...