这期内容当中小编将会给大家带来有关利用JAVA如何实现浮点数计算,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。
<强>问题:强>
对两个双类型的值进行运算,有时会出现结果值异常的问题。比如:
System.out.println (19.99 + 20); System.out.println (1.0 - -0.66); System.out.println (0.033 * 100); System.out.println (12.3/100);
<强>输出:强>
39.989999999999995 0.33999999999999997 3.3000000000000003 0.12300000000000001
Java中的简单浮点数类型浮点数和双精度数不能够精确运算。这个问题其实不是Java的错误,因为计算机本身是二进制的,而浮点数实际上只是个近似值,所以从二进制转化为十进制浮点数时,精度容易丢失,导致精度下降。
关于精度损失的原理可以很简单的讲,首先一个正整数在计算机中表示使用01010形式表示的,浮点数也不例外。
比如11日11除以2等于5余1
5除以2等于2余1
2除以2等于1余0
1除以2等于0余1
所以11个二进制表示为:1011 .
两类型占8个字节,64位,第1位为符号位,后11位面是指数部分,剩余部分是有效数字。
正整数除以2肯定会有个尽头的,之后二进制还原成十进制只需要乘以2即可。
举个例子:0.99用的有效数字部分,
0.99 * 2=1 + 0.98,比;1
0.98 * 2=1 + 0.96,比;1
0.96 * 2=1 + 0.92——在1
0.92 * 2=1 + 0.84——在1
,,,...............
这样周而复始是没法有尽头的,而双有效数字有限,所以必定会有损失,所以二进制无法准确表0.99示,就像十进制无法准确表示1/3一样。
<>强解决办法:强>
在《有效的Java》中提到一个原则,那就是浮点数和双精度数只能用来作科学计算或者是工程计算,但在商业计算中我们要用java.math.BigDecimal,通过使用BigDecimal类可以解决上述问题,首先需要注意的是,直接使用字符串来构造BigDecimal是绝对没有精度损失的,如果用双或者把双转化成字符串来构造BigDecimal依然会有精度损失,所以我觉得这种解决方法就是在使用中就把浮点数用字符串来表示存放,涉及到运算直接用字符串构造翻倍,否则肯定会有精度损失。
<强> 1。相加强>
/* * *相加 * @param double1 * @param double2 * @return */doubleValA公共静态双add(字符串,字符串doubleValB) { a2=new BigDecimal (doubleValA); b2=new BigDecimal (doubleValB); 返回a2.add (b2) .doubleValue (); }
<强> 2。相减强>
/* * *相减 * @param double1 * @param double2 * @return */doubleValA公共静态双接头(字符串,字符串doubleValB) { a2=new BigDecimal (doubleValA); b2=new BigDecimal (doubleValB); 返回a2.subtract (b2) .doubleValue (); }
<强> 3。相乘强>
/* * *相乘 * @param double1 * @param double2 * @return */doubleValA公共静态双mul(字符串,字符串doubleValB) { a2=new BigDecimal (doubleValA); b2=new BigDecimal (doubleValB); 返回a2.multiply (b2) .doubleValue (); }
<>强4。相除强>
/* * *相除 * @param double1 * @param double2 * @param规模除不尽时指定精度 * @return */doubleValA公共静态双div(字符串,字符串doubleValB, int规模){ a2=new BigDecimal (doubleValA); b2=new BigDecimal (doubleValB); 返回a2。分(b2,规模,BigDecimal.ROUND_HALF_UP) .doubleValue (); }
<强> 5。主函数调用强>
公共静态void main (String [] args) { 字符串doubleValA=?.14159267”; 字符串doubleValB=?.358”; System.out.println(添加:“;+添加(doubleValA doubleValB)); System.out.println(“子:“+子(doubleValA doubleValB)); System.out.println (mul:“;+ mul (doubleValA doubleValB)); System.out.println (“div:“+ div (doubleValA doubleValB 8)); }
结果展示如下所示:
添加:5.49959267 子:0.78359267 mul: 7.40787551586 div: 1.33231241
所以最好的方法是完全抛弃翻倍,用字符串和java.math。BigDecimal。
java遵照IEEE制定的浮点数表示法来进行漂浮,双运算。这种结构是一种科学计数法,用符号,指数和尾数来表示,底数定为2,即把一个浮点数表示为尾数乘以2的指数次方再添上符号。具体底层如何存储以及如何进行运行请继续关注我的博客,后续我会将详情总结好的。