美文网首页
BigDecimal精度的king

BigDecimal精度的king

作者: 我叫何家明 | 来源:发表于2022-04-27 08:44 被阅读0次

存储金额需要高精度才可。

double

double虽然是专用于浮点的基本数据类型,但是小数在十进制转二进制会有个无限循环,导致精度不准确。

BigDecimal原理

原理就是使用整数去存储,并且记住小数点的位置
从构造函数开始观察,推荐传入String,因为double会丢失精度,最后就是给四个变量赋值

 this.intVal = intVal;
        this.intCompact = compactVal;
        this.scale = scale;
        this.precision = prec;

Translates a double into a BigDecimal, with rounding according to the context settings. The scale of the BigDecimal is the smallest value such that (10scale × val) is an integer.

// The scale of this BigDecimal, as returned by 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.
此BigDecimal中的小数位数,如果位数未知,则为0(查找信息)。如果非零,则保证该值正确。如果值可能为0,请使用precision()方法获取并设置该值。该字段在设置为非零之前是可变的。
     *
     * @since  1.5
     */
    private transient int precision;

/**
     * 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.
如果此BigDecimal有效位的绝对值小于或等于Long。最大值,该值可以紧凑地存储在该字段中并用于计算。
     */
    private final transient long intCompact;

 /**
     * The unscaled value of this BigDecimal, as returned by {@link
     * #unscaledValue}.
     *
     * @serial
     * @see #unscaledValue
     */
    private final BigInteger intVal;

举个例子

new BigDecimal("123.2123");

可以知道,转成整数,长度为7位,小数有四位


image.png

equals,数字比较

比较整数及小数点位置是否相同。相关源码

/**
     * Compares this {@code BigDecimal} with the specified
     * {@code Object} for equality.  Unlike {@link
     * #compareTo(BigDecimal) compareTo}, this method considers two
     * {@code BigDecimal} objects equal only if they are equal in
     * value and scale (thus 2.0 is not equal to 2.00 when compared by
     * this method).
     *
     * @param  x {@code Object} to which this {@code BigDecimal} is
     *         to be compared.
     * @return {@code true} if and only if the specified {@code Object} is a
     *         {@code BigDecimal} whose value and scale are equal to this
     *         {@code BigDecimal}'s.
     * @see    #compareTo(java.math.BigDecimal)
     * @see    #hashCode
     */
    @Override
    public boolean equals(Object x) {
        if (!(x instanceof BigDecimal))
            return false;
        BigDecimal xDec = (BigDecimal) x;
        if (x == this)
            return true;
        if (scale != xDec.scale)
            return false;
        long s = this.intCompact;
        long xs = xDec.intCompact;
        if (s != INFLATED) {
            if (xs == INFLATED)
                xs = compactValFor(xDec.intVal);
            return xs == s;
        } else if (xs != INFLATED)
            return xs == compactValFor(this.intVal);

        return this.inflated().equals(xDec.inflated());
    }

最精彩的加减乘除

这里用加法的源码做demo

// Arithmetic Operations
    /**
     * Returns a {@code BigDecimal} whose value is {@code (this +
     * augend)}, and whose scale is {@code max(this.scale(),
     * augend.scale())}.
     *
     * @param  augend value to be added to this {@code BigDecimal}.
     * @return {@code this + augend}
     */
    public BigDecimal add(BigDecimal augend) {
        if (this.intCompact != INFLATED) {
            if ((augend.intCompact != INFLATED)) {
                return add(this.intCompact, this.scale, augend.intCompact, augend.scale);
            } else {
                return add(this.intCompact, this.scale, augend.intVal, augend.scale);
            }
        } else {
            if ((augend.intCompact != INFLATED)) {
                return add(augend.intCompact, augend.scale, this.intVal, this.scale);
            } else {
                return add(this.intVal, this.scale, augend.intVal, augend.scale);
            }
        }
    }

相关文章

网友评论

      本文标题:BigDecimal精度的king

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