我有以下代码来获取百分比:
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
如何处理此类问题?
答案 0 :(得分:2)
让我们这样看。内存和通讯很便宜。
BigDecimal totalPrice = new BigDecimal(double 215.00);
int numNight = 3;
BigDecimal perNightPrice = totalPrice
.divide(new BigDecimal(int numNight), BigDecimal.ROUND_HALF_EVEN)
.setScale(2, BigDecimal.ROUND_HALF_EVEN);
此时,您具有三个变量。鉴于内存(主RAM和辅助磁盘/ DB)和通信都很便宜,您只需保留totalPrice变量即可。您无需从perNightPrice和numNight对它进行反向工程。
我以前曾遇到过这种情况。我们只是更改了API和/或数据表定义,以允许我们保留更多数据(除非您要在Lunar-Lander中寻找内存,否则我会怀疑,因为Lunar-Lander不计算酒店价格) 。
答案 1 :(得分:2)
我的感觉是,这里的问题不是丢弃原始价格之一,而是通过将小数点后的值舍去到两位小数来丢弃有价值的信息。如果您再保留一位小数,就不会有这个问题。
这里是一个示例,该示例保留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
答案 2 :(得分:1)
可以提高到一定精度吗?
final BigDecimal price = BigDecimal.valueOf(215).setScale(10, BigDecimal.ROUND_HALF_EVEN);
final BigDecimal daysOfThisReservation = BigDecimal.valueOf(3).setScale(10, BigDecimal.ROUND_HALF_EVEN);