美文网首页jdk
BigDecimal为什么可以精确计算

BigDecimal为什么可以精确计算

作者: 飞哈飞 | 来源:发表于2020-11-12 20:41 被阅读0次

为什么浮点数无法精确计算

计算机底层只能用二进制表示数,因此只能精确表示x*2^y类型的数,不能被此形式计算得来的数则只能通过多精度的方式近似地表示出来。

底层数字表示

BigDecimal能更精确表示带小数点的数值,因为采用了long intCompact和int scale来表示数值,
如果位数过大,不能用intCompact表示还会用BigInteger这个对象来表示大数字,本质是一个整形数组,而不是浮点型的科学计数法。

 /**
     * The unscaled value of this BigDecimal, as returned by {@link
     * #unscaledValue}.
     *
     * @serial
     * @see #unscaledValue
     */
    private final BigInteger intVal;
    /**
     * The scale of this BigDecimal, as returned by {@link #scale}.
     *
     * @serial
     * @see #scale
     */
    private final int scale;  // Note: this may have any value, so
                              // calculations must be done in longs
    /**
     * The number of decimal digits in this BigDecimal, or 0 if the
     * number of digits are not known (lookaside information).  If
     * nonzero, the value is guaranteed correct.  Use the precision()
     * method to obtain and set the value if it might be 0.  This
     * field is mutable until set nonzero.
     *
     * @since  1.5
     */
    private transient int precision;
    /**
     * Sentinel value for {@link #intCompact} indicating the
     * significand information is only available from {@code intVal}.
     */
    static final long INFLATED = Long.MIN_VALUE;

    private static final BigInteger INFLATED_BIGINT = BigInteger.valueOf(INFLATED);

    /**
     * If the absolute value of the significand of this BigDecimal is
     * less than or equal to {@code Long.MAX_VALUE}, the value can be
     * compactly stored in this field and used in computations.
     */
    private final transient long intCompact;

乘法计算

判断结果是否会溢出,不会就直接是long*long,溢出则会调用BigInteger的乘法

 private static long multiply(long x, long y){
                long product = x * y;
        long ax = Math.abs(x);
        long ay = Math.abs(y);
        if (((ax | ay) >>> 31 == 0) || (y == 0) || (product / y == x)){
                        return product;
                }
        return INFLATED;
    }

    private static BigDecimal multiply(long x, long y, int scale) {
        long product = multiply(x, y);
        if(product!=INFLATED) {
            return valueOf(product,scale);
        }
        return new BigDecimal(BigInteger.valueOf(x).multiply(y),INFLATED,scale,0);
    }

    private static BigDecimal multiply(long x, BigInteger y, int scale) {
        if(x==0) {
            return zeroValueOf(scale);
        }
        return new BigDecimal(y.multiply(x),INFLATED,scale,0);
    }

    private static BigDecimal multiply(BigInteger x, BigInteger y, int scale) {
        return new BigDecimal(x.multiply(y),INFLATED,scale,0);
    }

相关文章

  • BigDecimal为什么可以精确计算

    为什么浮点数无法精确计算 计算机底层只能用二进制表示数,因此只能精确表示x*2^y类型的数,不能被此形式计算得来的...

  • 笔记一:DecimalFormat & BigDecimal

    一、DecimalFormat(数字格式化) 例1: 例2: 二、BigDecimal(精确计算) 为什么要用到B...

  • Kotlin BigDecimal 精确计算

    完整工具类 setScale 方法用于格式化小数点 其它计算方式说明 ROUND_UP舍入远离零的舍入模式。在丢弃...

  • 使用BigDecimal进行精确计算

    首先我们先来看如下代码示例: 因为计算机是二进制的,我们的浮点型无法精确的用二进制表示(2.4的二进制表示并非就是...

  • Java中的常用类

    BigDecimal(掌握) float和double都不能表示精确的小数,使用BigDecimal类可以解决该问...

  • BigDecimal使用(整理)

    应用场景 大多数的商业计算中,一般采用java.math.BigDecimal类来进行精确计算。比如:货币 使用 ...

  • BigDecimal常用方法以及 精确计算

    1.简介 BigDecimal类位于java.math.BigDecimal包下。使用此类可以完成大的小数操作,而...

  • BigDecimal大精度小数

    BigDecimal用于精度计算 输出结果: 在计算数值的时候,由于浮点数没有办法精确的对二进制进行计算,所以经常...

  • 常见对象BigDecimal的概述

    BigDecimal的概述 由于在运算的时候,float类型和double很容易丢失精度,所以为了能精确表示,计算...

  • 2019-04-10

    浮点数的精确计算用BigDecimal switch-case: 匹配成功会返回当前的case值,若有break则...

网友评论

    本文标题:BigDecimal为什么可以精确计算

    本文链接:https://www.haomeiwen.com/subject/foopbktx.html