存储金额需要高精度才可。
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位,小数有四位
![](https://img.haomeiwen.com/i6346382/9d56e59b8a2e8b44.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);
}
}
}
网友评论