BigDecimal初始化不要用double类型
在进行单价、总价相关的计算时,就会用到BigDecimal。
在初始化时,一个不小心,就可能给自己挖坑。
示例如下:
public class BigDecimalInitTest {
public static void main(String[] args) {
BigDecimal amount1=new BigDecimal("0.06");
BigDecimal amount2=new BigDecimal(0.06);
System.out.println(amount1);
System.out.println(amount2);
}
}
运行之后,结果为:
0.06
0.059999999999999997779553950749686919152736663818359375
源码注释
打开BigDecimal的构造方法,可以发现:
/**
* Translates a {@code double} into a {@code BigDecimal} which
* is the exact decimal representation of the {@code double}'s
* binary floating-point value. The scale of the returned
* {@code BigDecimal} is the smallest value such that
* <tt>(10<sup>scale</sup> × val)</tt> is an integer.
* <p>
* <b>Notes:</b>
* <ol>
* <li>
* The results of this constructor can be somewhat unpredictable.
* One might assume that writing {@code new BigDecimal(0.1)} in
* Java creates a {@code BigDecimal} which is exactly equal to
* 0.1 (an unscaled value of 1, with a scale of 1), but it is
* actually equal to
* 0.1000000000000000055511151231257827021181583404541015625.
* This is because 0.1 cannot be represented exactly as a
* {@code double} (or, for that matter, as a binary fraction of
* any finite length). Thus, the value that is being passed
* <i>in</i> to the constructor is not exactly equal to 0.1,
* appearances notwithstanding.
*
* <li>
* The {@code String} constructor, on the other hand, is
* perfectly predictable: writing {@code new BigDecimal("0.1")}
* creates a {@code BigDecimal} which is <i>exactly</i> equal to
* 0.1, as one would expect. Therefore, it is generally
* recommended that the {@linkplain #BigDecimal(String)
* <tt>String</tt> constructor} be used in preference to this one.
*
* <li>
* When a {@code double} must be used as a source for a
* {@code BigDecimal}, note that this constructor provides an
* exact conversion; it does not give the same result as
* converting the {@code double} to a {@code String} using the
* {@link Double#toString(double)} method and then using the
* {@link #BigDecimal(String)} constructor. To get that result,
* use the {@code static} {@link #valueOf(double)} method.
* </ol>
*
* @param val {@code double} value to be converted to
* {@code BigDecimal}.
* @throws NumberFormatException if {@code val} is infinite or NaN.
*/
public BigDecimal(double val) {
this(val,MathContext.UNLIMITED);
}
大体意思就是,BigDecimal(double val)这个构造方法有时是无法精确预料的,
传入0.1,有可能变成0.1000000000000000055511151231257827021181583404541015625。
因为double类型无法精确地存储0.1
IDEA编码提示
IDEA也会在编码时给出提示。
结论
通过double类型初始化的BigDecimal类型,是不精确的。
最好用String类型的数值字符串来初始化。
分类:
其他--java
, A1-java代码块积累
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2018-09-03 分布式系统的简单理解