当前位置: 首页 > 科技观察

公司同事用Float和Double,结果就是..

时间:2023-03-13 13:34:24 科技观察

BigDecimal这个相信大家都很熟悉了。只要你公司的业务涉及到一些更精确的数字,你就会用BigDecimal而不是用它。float和double,而且在设计数据库的时候,如果是decimal类型,会让你用BigDecimal,而不是float和double。为什么?阿芬会解释。float和doublefloat单精度浮点数在机器中占用4个字节,用32位二进制描述double双精度浮点数在机器中占用8个字节,用64位二进制描述注意数据float类型定义的最后必须有"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.399999999呢?这意味着当不进行浮点运算时,浮点数可以正确显示为十进制。也就是说,如果你的知识把类型定义为float,但是你不用这个数去计算,那还好,但是一旦你参与了计算,就不行了,分分钟被diss。阿里巴巴手册将数据库的小数类型定义为decimal,禁止使用float和double。在存储的时候,float和double都存在精度损失的问题,比较值的时候很有可能得到不正确的结果。如果存储数据的范围超出小数范围,建议将数据拆分成整数和小数分开存储。Java程序:使用BigDecimal定义值,然后进行浮点运算。BigDecimal是Java在java.math包中提供的API类。用于对有效位数大于16位的数字进行精确运算。使用BigDecimal需要注意的事项1.BigDecimal(double)创建一个对象,其值为参数指定的双精度值,但不推荐使用该类型。为什么不推荐?让我们试试BigDecimal。bigDecimal=newBigDecimal(0.2);System.out.println(bigDecimal);这段代码写的时候觉得没什么问题,但是输出的时候却一头雾水。0.20000000000000011102230246251565404236316680908203125又出现精度问题?事实上,当你点击这个方法查看源码时,注释提醒你要谨慎。*Theresultsofthisconstructorcanbesomewhatunpredictable.这个构造函数可以有些不可预测的结果*Onemightassumethatwriting{@codenewBigDecimal(0.1)}in*Javacreatesa{@codeBigDecimal}whichisexactlyequalto*0.1(anunscaledvalueof1,withascaleof1),butitis*actuallyequalto*0.1000000000000000055511151231257827021181583404541015625.*Thisisbecause0.1cannotberepresentedexactlyasa*{@codedouble}(或者,就此而言,作为*任何有限长度的二进制分数)。因此,传递给构造函数的值*不完全等于0.1,*尽管有外观。阿芬看到第一句话就知道以后不应该用double数据类型初始化bigDecimal,不靠谱。也就是说,存在精度丢失的风险,在精确计算或者数值比较场景下,可能会导致业务逻辑异常。由于不推荐使用BigDecimal(double)。那么推荐什么呢?BigDecimal(string)或者使用valueofBigDecimalbigDecimal=newBigDecimal("0.2");System.out.println(bigDecimal);BigDecimalbigDecimal1=BigDecimal.valueOf(0.2);System.out.println(bigDecimal1);这时候看看和我们预期的结果一样。0.20.2这两个其实是一个,valueof只是帮我们在源码中把double转成Double.toString(val),即还是string。这就是为什么有些面试官在基础面试的时候会问很多次,float和double会丢精度,BigDecimal会不会丢精度?为什么?如果你回答的时候不失准,恭喜你,你很酷,如果你的回答会失准,那么面试官肯定会问什么情况下会失准,什么情况下不会失准。这也是为什么在《EffectiveJavaandMysqlEssentialContentBooks》中提到这部分内容的原因。如果你是有几年工作经验的人,就不会出现这种错误,但如果你是初入职场,就没有那么多经验了。基础没那么扎实肯定会出这种事的,去查查你们公司的代码。BigDecimal的加减乘除加法:加减法:减法乘法:乘除法:除法BigDecimal保留小数点问题ROUND_DOWN:向零舍入ROUND_UP:向0舍入ROUND_CEILING:向正无穷大舍入ROUND_FLOOR:向负无穷大舍入ROUND_HALF_DOWN:相当于四舍五入ROUND_HALF_UP:相当于四舍五入(经常用到)以上就是阿芬要跟大家说的BigDecimal。您想查看您公司的代码吗?