知识点
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 位小数,现在好家伙几十位。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于