码迷,mamicode.com
首页 > 其他好文 > 详细

BigDecimal初始化不要用double类型

时间:2019-09-03 09:53:48      阅读:84      评论:0      收藏:0      [点我收藏+]

标签:rac   ring   param   cal   creat   time   therefore   except   构造方法   

在进行单价、总价相关的计算时,就会用到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> &times; 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类型的数值字符串来初始化。

BigDecimal初始化不要用double类型

标签:rac   ring   param   cal   creat   time   therefore   except   构造方法   

原文地址:https://www.cnblogs.com/expiator/p/11450684.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!