为什么大厂都禁止使用BigDecimal(double)构造函数

305 阅读1分钟

BigDecimal一个用于进行更加精确的金额计算的封装类型

public BigDecimal(double val, MathContext mc) {
    // 如果val是无限大的数或不是数字,抛出异常
    if (Double.isInfinite(val) || Double.isNaN(val))
        throw new NumberFormatException("Infinite or NaN")
        
    // 根据双精度小数,转换为符号位,阶数和有效位根据JLS的公式 20.10.22
    // 1. 根据IEEE754标准 将双精度浮点数 bit格式转换为long类型 
    // 如果这里输入double值为0.1,无法精确转换为二进制,得出的结果是错误的
    long valBits = Double.doubleToLongBits(val);
    // 2. 将valBits右移63位保留符号位,判断正负数 (0:正数,1:负数)
    int sign = ((valBits >> 63) == 0 ? 1 : -1);
    // 3. 获取阶码部分
    int exponent = (int) ((valBits >> 52) & 0x7ffL);
    // 4. 获取有效位
    long significand = (exponent == 0
            ? (valBits & ((1L << 52) - 1)) << 1
            : (valBits & ((1L << 52) - 1)) | (1L << 52));
    略.......
    .......
    .......
}

在上面的代码中 double转换为二进制时,不是所有的小数都能够正确转换的,如0.1二进制为0.000110011001100…一个无限循环的二进制 这就会造成进度丢失