在進行單價、總價相關的計算時,就會用到BigDecimal。
在初始化時,一個不當心,就可能給本身挖坑。app
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); } }
運行以後,結果爲:ide
0.06 0.059999999999999997779553950749686919152736663818359375
打開BigDecimal的構造方法,能夠發現:this
/** * 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類型的數值字符串來初始化。code