使用JodaDateTime计算日期差转BigDecimal小数结果不符合预期问题
问题成因
核心原因是Java的整数除法默认截断小数位:
- 代码中
numberOfDays为int类型,常量365默认也是int类型,执行numberOfDays/365时会走整数运算逻辑,直接丢弃小数部分,702除以365的整数运算结果就是1。 - 后续将运算结果转为
BigDecimal、再设置保留小数位的操作,都是基于已经丢失精度的1执行,自然只能得到1.00的结果,无法得到预期的1.92。
修复方案
推荐直接用BigDecimal的内置除法运算完成计算,全程保证精度,不会出现浮点运算的精度丢失问题,修改后的代码如下:
import java.math.BigDecimal; import java.math.RoundingMode; import java.util.Date; import org.joda.time.DateTime; import org.joda.time.Days; private BigDecimal getNumberOfYearsService(Date startServiceDate, Date endServiceDate) { DateTime startServiceDateTime = new DateTime(startServiceDate); DateTime endServiceDateTime = new DateTime(endServiceDate); int numberOfDays = Days.daysBetween(startServiceDateTime, endServiceDateTime).getDays(); // 先将天数转为BigDecimal,再和365的BigDecimal值做除法,同时指定精度和舍入模式 return BigDecimal.valueOf(numberOfDays) .divide(BigDecimal.valueOf(365), 2, RoundingMode.HALF_UP); }
当numberOfDays为702时,上述代码会直接返回1.92的预期结果。
补充说明:如果不需要严格规避浮点精度问题,也可以把除数改为浮点型
365.0触发浮点除法,即new BigDecimal(numberOfDays/365.0).setScale(2,RoundingMode.HALF_UP),但该方案在高精度要求场景下不如直接用BigDecimal除法稳妥。
内容的提问来源于stack exchange,提问作者Orby
相关产品推荐
相关产品推荐

