知识点
CompareTo
算式 | 使用 | compareTo 值 |
---|---|---|
a == b | a.compareTo(b) | 0 |
a > b | a.compareTo(b) | 1 |
a < b | a.compareTo(b) | -1 |
推理:
例子 | 推荐 code | 不推荐 code |
---|---|---|
a > b | a.compareTo(b) > 0 | a.compareTo(b) == 1 |
a >= b | a.compareTo(b) >= 0 | a.compareTo(b) > -1 |
a < b | a.compareTo(b) < 0 | a.compareTo(b) == -1 |
a <= b | a.compareTo(b) <=0 | a.compareTo(b) < 1 |
a == b | a.compareTo(b) == 0 | a.compareTo(b) == 0 |
加减乘除
+-*/ | 表达式 |
---|---|
加 | add(BigDecimal) |
减 | subtract(BigDecimal) |
乘 | multiply(BigDecimal) |
除 | divide(BigDecimal) |
equals
a 值 | b 值 | a.equals(b)值 |
---|---|---|
BigDecimal(1000) | BigDecimal(1000) | ture |
BigDecimal(1000) | BigDecimal("1000") | true |
BigDecimal(100.01) | BigDecimal("100.01") | false |
BigDecimal(100.01) | BigDecimal(100.0100) | true |
BigDecimal("100.01") | BigDecimal("100.0100") | false |
推理:
equals 比较时候相等时候
采用 double 构建和小数位数无关,采用 String 构建与小数位数有关
double 与 String 构建的 BigDecimal,值一样但也是 false
故事
就说说最近吧,最近上班经常用到了一个东西 BigDecimal,然后对我我这不爱动脑的人来说就很要命了,为什么这种说(接下来就尽情嘲笑我吧),我每次用到比较大小都去百度一次,有个哥们那个博客怕被我访问了 100 来次,但是还是记不住,就是因为他用了上面我写了不推荐的那个写法,搞得我头昏眼花,今天咬咬牙,来写写,加深印象。
我每次用到 BigDecimal 的时候,经常要比较大小,这时候呢,我这脑子就不好用了,分不清谁大谁小,当时我脑子大概是这样想的:compareTo 等于 1 是左边大还是又边大,等于-1 了,如果要大于等于怎么办。
搞事情(理论)
compareTo 源码分析
public int compareTo(BigDecimal val) {
//判断小数位数,区别出是否是字符串构造
//如果是int或者long则为0,double 则scale是46,但如果是字符串,则有几位算几位
if (scale == val.scale) {//相等说明是int或者long
//xs ys 通过移位以及其他运算得出可用于计算的值
long xs = intCompact;
long ys = val.intCompact;
if (xs != INFLATED && ys != INFLATED) //判断时候超过INFLATED -2的63次方
//这就是为什么返回的是 0 1 -1的原因
return xs != ys ? ((xs > ys) ? 1 : -1) : 0;
}
//判断signum函数 具体signum函数是什么鬼自己google
//具体为正负0:0,正:1,负:-1 NaN:NaN
int xsign = this.signum();
int ysign = val.signum();
if (xsign != ysign)
return (xsign > ysign) ? 1 : -1;
if (xsign == 0)
return 0;
//忽略符号进行比较 无符号的compareTo
int cmp = compareMagnitude(val);
return (xsign > 0) ? cmp : -cmp;
}
equals 源码分析
@Override
public boolean equals(Object x) {
//常规查看类型
if (!(x instanceof BigDecimal))
return false;
//将Object强转
BigDecimal xDec = (BigDecimal) x;
//对比内存地址
if (x == this)
return true;
//对比小数位数,注意:为什么我们采用字符串构建和double构建,虽然小数位数看着一样,但是是false的原因,double的scale有40多位,但是如果是字符串则有几位是几位
if (scale != xDec.scale)
return false;
//移位运算计算可用于计算的紧凑值
long s = this.intCompact;
long xs = xDec.intCompact;
if (s != INFLATED) {//-2的63次方
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());//开始值比较
}
与 Double 比较
采用 Double 很严重一个问题就是精度问题
为什么在很多的项目中会采用 BigDecimal 而不采用 double 呢,或许你有时候也会遇到前端页面显示价格会有 8/9 位小数,这就是因为精度的原因。举个例子当你计算钱或者货物。eg:有个老板有很多的黄金。现在金价 1g 算 350,他本来有 0.03 吨(30kg),这个时候卖了 0.02 吨(20kg),如果是 Double 的话他现在还剩多少?还剩下结果是 0.009999999999998;哦豁,本来只是 2 位小数,现在好家伙几十位。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于