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> &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类型的数值字符串来初始化。

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

时间: 2024-08-05 01:31:56

BigDecimal初始化不要用double类型的相关文章

java中如何使用BigDecimal使得Double类型保留两位有效数字

一.场景:从数据表中读出Decimal类型的数据直接塞给Double类型的对象时,并不会有什么异常. 如果要再此基础上计算,就会发生异常. 比如:读出数据为0.0092,将其乘以100,则变成了0.919999999999999... 二.原因: java mysql 数据类型对照如下: 类型名称 显示长度 数据库类型 JAVA类型 JDBC类型索引(int) 描述             VARCHAR L+N VARCHAR java.lang.String 12   CHAR N CHAR

关于java中Double类型的运算精度问题

标题     在Java中实现浮点数的精确计算    AYellow(原作) 修改    关键字     Java 浮点数 精确计算   问题的提出:如果我们编译运行下面这个程序会看到什么?public class Test{    public static void main(String args[]){        System.out.println(0.05+0.01);        System.out.println(1.0-0.42);        System.out.

float及double类型减法运算时精度丢失问题

当float和double类型在进行减法运算时,会出现精度丢失问题,这种问题主要是由于计算机中普遍使用2进制所造成的.在此做为记录,防止日后遗忘.     public static void main(String[] args) {         float a = 2.1f;         float b = 2.0f;         float c = a - b;         System.out.println("a-b=" + c);     }     //输

Java中double类型的数据精确到小数点后两位

Java中double类型的数据精确到小数点后两位 多余位四舍五入,四种方法 一: double f = 111231.5585;BigDecimal b = new BigDecimal(f); double f1 = b.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue(); 二: new java.text.DecimalFormat("#.00").format(3.1415926) 三: double d = 3.1415926

Java学习笔记--double类型数据精度

在一次面试中被问到,有两个double类型的数相减,会出现精度丢失,应该怎么办,有什么解决方法.今天特地去搜了下,解决方法就是用BigDecimal类对数据进行处理. 了解详细参考:http://blog.csdn.net/u011328015/article/details/43969129

Double 类型运算时的精度问题

double 类型运算时的 计算的精度不高,经常会出现0.999999999999999这样的情况,那么就需要用BigDecimal   它是java提供的用来高精度计算的工具类 下面是对这个类的一个包装,方便使用: package cn.soft.util; import java.io.Serializable; import java.math.BigDecimal; import org.springframework.stereotype.Component; /** *类描述: do

关于double类型数字相加位数发生变化的问题

?? 因为计算机内部存贮本身的缺陷,导致double类型的数字相加.得到的结果有非常多位,比方 774.23 750.0 2638.66 4162.889999999999 看到这个是不是非常晕 当然也有解决方式 new BigDecimal(Double.toString(a)).add( new BigDecimal(Double.toString(b))).add( new BigDecimal(Double.toString(c))) 用BigDecimal和add.问题迎刃而解 774

java中如果需要精确的计算答案,请避免使用double类型与float类型

double类型与float类型主要用于科学计算与工程计算而设计的,用于二进制浮点计算.对于普通计算通常是结果不准确的,所以对于普通的浮点数的加减法等,解决的方法需要用int,long,BigDecimal来计算. 1.计算出现的问题? 计算结果如下: 显然结果不是我们所需要的.我们需要的结果是:0.88 所以,我们的程序应该这样写: 1 public static void main(String[] args) { 2 BigDecimal a=BigDecimal.valueOf(1.29

java中数字加减乘除乱象(尤其是double类型)

 做一个300 / 1570 的算数题,结果为0 是不是有点大跌眼镜 那怎么解决呢 转成Double类型,再除就没问题了 import java.math.BigDecimal; public class Arith { private static final int DEF_DIV_SCALE = 10; /** * * 两个Double数相加 * * * @param v1 * * @param v2 * * @return Double */ public static Double