java - 如何在 Java 中处理 BigDecimal 中的舍入

标签 java bigdecimal

我有这段代码来获取百分比:

final BigDecimal price = BigDecimal.valueOf(215).setScale(2, BigDecimal.ROUND_HALF_EVEN);
final BigDecimal daysOfThisReservation = BigDecimal.valueOf(3).setScale(2, BigDecimal.ROUND_HALF_EVEN);

final BigDecimal dayPrice = price.divide(daysOfThisReservation, BigDecimal.ROUND_HALF_EVEN).setScale(2, BigDecimal.ROUND_HALF_EVEN);

System.out.println(dayPrice); //71.67
System.out.println(dayPrice.multiply(daysOfThisReservation).setScale(2, BigDecimal.ROUND_HALF_EVEN)); //215.01

我有一个 215.00 美元的预订,这个预订每天有 3 个, 所以,价格是 71.67 美元。

如果我再次尝试获取原始值,我会遇到一些舍入问题,71.67 * 3 = 215.01

如何处理这类问题?

最佳答案

我的感觉是,这里的问题不是丢弃原始价格,而是通过将小数值截断到小数点后两位来丢弃有值(value)的信息。如果您多保留一位小数,就不会出现此问题。

这是一个保持 6 位精度的示例,以允许足够的精度对值进行数百次操作,而我最终只需要两位有效的小数位。如果你最后只关心 2 位,你将永远不会遇到小数点后 6 位的舍入问题。

此代码保留 6 位,但打印单日价格时除外,此时四舍五入为 2 位。

final BigDecimal price = BigDecimal.valueOf(215).setScale(6, BigDecimal.ROUND_HALF_EVEN);
final BigDecimal daysOfThisReservation = BigDecimal.valueOf(3).setScale(6, BigDecimal.ROUND_HALF_EVEN);

final BigDecimal dayPrice = price.divide(daysOfThisReservation, BigDecimal.ROUND_HALF_EVEN).setScale(6, BigDecimal.ROUND_HALF_EVEN);

System.out.println(dayPrice.setScale(2, BigDecimal.ROUND_HALF_EVEN));
System.out.println(dayPrice.multiply(daysOfThisReservation).setScale(2, BigDecimal.ROUND_HALF_EVEN)); //215.01

结果:

71.67
215.00

关于java - 如何在 Java 中处理 BigDecimal 中的舍入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55699208/

相关文章:

java - Java 的 BufferedReader.readLine() 是否将整个文件放入内存?

java - 如何将 BigDecimal 值四舍五入到最接近的百分之一

java - 是否有 API 方法可以将 BigDecimal(秒) 转换为年、月、日、小时、分钟、秒?

android - BigDecimal 在带有本地化的 Android 4.0.3 中给出 NumberFormatException

java - 创建管理器类或包装类

java - 以我不需要安装的方式嵌入Java3D是不可能的吗?

java - 我应该从多个线程访问(而不是更改)一个对象吗?

java - 如何在 Java 中将任何数组作为参数传递?

Java 16 记录 BigDecimal equals & hashcode

java - BigDecimal.setScale(int,int)和RoundingMode枚举不推荐使用的构造函数