BigDecimal的辉煌橱柜相信大家都很熟悉这一点。只要你公司的业务涉及到一些精确的数字,你就会用BigDecimal来代替float和double,而在设计数据库的时候,如果是Decimal类型,你也会用BigDecimal来代替Float和double。为什么呢?糟糕的橱柜来解释。
float和double
float单精度浮点数在计算机中占用4个字节,用32位二进制描述。双浮点数在计算机中占8个字节,用64位二进制来描述。
请注意,浮点类型定义的数据必须在末尾有“f”或“f”,以便与double区分开来。
让我们写一个简单的程序来实验为什么它不起作用。
system . out . println(2.0-1.4);
如果你是一个有经验的开发人员,你觉得这样写有问题吗?这个直接减法的数据应该是错的。是的,结果肯定是错的。
0.6000000000000001
为什么手术结果有问题?那加法和乘法会有这种问题,恭喜你,我觉得,确实会有这种问题,而且这个问题还得从我们的电脑上讨论,我们的电脑除了二进制数据,是不能识别任何数据的。也就是说,我们传递给计算机的是十进制数据,但计算机需要先把我们给出的数据转换成二进制数据,因为它不能直接识别十进制数据。这时,2.0是十进制数据并转换成二进制数据,而1.4?相反,数据转换成二进制存在问题。1.4二进制中,会有1.399999。这种数据,当我们进行数据转换时,就出现了2.0-1.399999的数据。
这时有人问,为什么我把float类型定义为1.4的时候不是1.39999999?这是当不执行浮点计算时,浮点数可以在十进制中正确显示。也就是说,如果你的知识把类型定义为float,但是你不用这个数来计算,那没问题,但是一旦你参与计算,那就行不通了。分秒必争。
阿里手册定义
数据库十进制类型,禁止浮点和双精度。存储时,float和double都有精度损失的问题,比较值时很可能会得到不正确的结果。如果存储的数据范围超过小数的范围,建议将数据拆分为整数和小数,分别存储。
Java程序:用BigDecimal定义值,然后进行浮点算术运算。
BigDecimal是Java在java.math包中提供的API类,用于精确计算有效位超过16位的数字。
00-1010 1.bigdecimal (double)使用参数指定的双精度值创建对象。
但是不推荐这种类型。为什么不呢?让我们试试。
BigDecimal bigDecimal=新的big decimal(0.2);
system . out . println(BigDecimal);
当rydxhd编写这段代码时,感觉很好,但当它被输出时,就很愚蠢。
0.200000000000000011102230246251565404236316680908203125
精度问题又来了?事实上,当rydxhd点击这个方法查看源代码时,注释会提醒您要谨慎。
*这个构造函数的结果可能是不可预测的。这个构造函数可能会有一些不可预测的结果。
*人们可能会假设在中编写{@code new BigDecimal(0.1)}
* Java创建了一个{@code BigDecimal},它完全等于
* 0.1(未缩放值1,比例为1),但它是
*实际相等
to * 0.1000000000000000055511151231257827021181583404541015625. * This is because 0.1 cannot be represented exactly as a * {@code double} (or, for that matter, as a binary fraction of * any finite length). Thus, the value that is being passed * <i>in</i> to the constructor is not exactly equal to 0.1, * appearances notwithstanding.烂漫的柜子看到第一句话的时候,就知道,以后别用 double 数据类型去初始化这个 bigDecimal 了,不靠谱呀。
也就是说存在精度损失风险,在精确计算或值比较的场景中可能会导致业务逻辑异常
既然不推荐使用 BigDecimal(double)。那么推荐使用什么呢?
BigDecimal(string) 或者使用 valueof
BigDecimal bigDecimal = new BigDecimal("0.2"); System.out.println(bigDecimal); BigDecimal bigDecimal1 = BigDecimal.valueOf(0.2); System.out.println(bigDecimal1);这时候,我们再来看看是否和我们预期的结果是一样的。
0.2 0.2这两个实际上都是一个,valueof 只不过是在源码中帮我们把 double 被变换成了 Double.toString(val) ,也就是还是string。
这就是为什么有些面试官在面试基础的时候,很多次会问,float 和 double 都会丢失精度,BigDecimal 会丢失精度吗?为什么?
你如果回答不会丢失精度,那恭喜你,你凉了,如果你回答会丢失精度,那么面试官肯定会追问到什么情况会丢失精度,什么情况不会丢失精度。
这也是为什么在 Effective Java 和 Mysql 必会内容 书中都会提到这块内容,如果你是一个几年工作经验的人,就不会有这种错误,但是你初入职场,经验没那么多,基础没那么牢固的肯定会发生这种事,赶快去检查一下你们公司的代码吧。
BigDecimal 的加减乘除
加法:add
减法:subtract
乘法:multiply
除法:divide
BigDecimal保留小数点问题
ROUND_DOWN :向零方向舍入
ROUND_UP :向远离0的方向舍入
ROUND_CEILING:向正无穷方向舍入
ROUND_FLOOR :向富无穷方向舍入
ROUND_HALF_DOWN:相当于五舍六入
ROUND_HALF_UP:相当于四舍五入(经常使用)
以上就是烂漫的柜子想给大家说的关于 BigDecimal 的内容了,你要去看看你公司的代码么?