BigDecimal进⾏浮点数精确计算错误⽤法和正确⽤法
前⾔
通常商业计算涉及到⼩数的,我们都会使⽤BigDecimal来完成加减乘除运算。但是利⽤BigDecimal进⾏浮点数精确运算时,需要注意使⽤正确的⽅法。如果⽅法选择不当,依旧会发⽣错误。
发现问题
测试BigDecimal的两种构造⽅法,发现浮点运算的结果不同。
利⽤BigDecimal.valueOf⽅法构造对象的⽅法,获得的浮点数发⽣了精度异常。
利⽤new BigDecimal(String val)⽅法,运算正确。
分析原因
查看BigDecimal.valueOf源码,我们可以发现问题。BigDecimal.valueOf(9.9f),实际调⽤的⽅法是:
java.math.BigDecimal#valueOf(double)。如下图所⽰。
⽐我们想象的多了⼀步强制类型转换的动作。9.9f会被强制转换成double类型。测试这个强制转换,我们可以发现问题,其实出在强制转换这⾥。强制转换结果如下图所⽰。
拓展
假如参数是double类型,我们使⽤BigDecimal.valueOf(…)可以吗?
看结果是没问题的。但是,注意BigDecimal.valueOf(…)的源码,其内部依然是把⼊参转换了double数据对应的字符串。
假如直接使⽤new BigDecimal(double val)构造函数来进⾏运算,则会发现计算结果发⽣来精度异常。如下图所⽰。
可以看到jdk内部的注释,已经说明,new BigDecimal(double val)⽅法得到的结果是不可预知的。推荐使⽤⼊参类型为String的构造函数
可以看到jdk内部的注释,已经说明,new BigDecimal(double val)⽅法得到的结果是不可预知的。推荐使⽤⼊参类型为String的构造函数来进⾏浮点数的精确计算。
总结
bigdecimal格式化两位小数
1、在使⽤BigDecimal进⾏科学运算的时候,我们需要清楚,BigDecimal.valueOf(…)和new BigDecimal(…)的使⽤效果不同。当BigDecimal.valueOf(…)的⼊参是float类型时,BigDecimal会把⼊参强制转换成double类型。
2、使⽤new BigDecimal(String val)来获得浮点数对应的BigDecimal对象,进⽽完成浮点数精确运算。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。