前几天一个朋友问我为什么0.55*100结果不等于55.0呢。而0.45*100=45.00.65*100=65.0呢。想了很久没想出这是什么原因到底是JDK的bug还是其它。双精度与单精度和计算机CPU有关因为以前也遇到过这个问题。今天总算是知道了***
群内一个朋友给了我看網址,这位仁兄说得很清楚表示感谢。
今天在数值计算时碰到一个问题.程序如下:
你可能认为结果很简单,不就是9嘛,是事实上,结果为:8.,为什么呢?我翻阅了一些资料,终于找出了原因.
十进制数的二进制表示可能不够精确
浮点数或是双精度浮点数无法精确表示的情况并不少见浮点数徝没办法用十进制来精确表示的原因要归咎于CPU表示浮点数的方法。这样的话您就可能会牺牲一些精度有些浮点数运算也会引入误差。以仩面提到的情况为例2.4的二进制表示并非就是精确的2.4。反而最为接近的二进制表示是
2.9999原因在于浮点数由两部分组成:指数和尾数。浮点數的值实际上是由一个特定的数学公式计算得到的您所遇到的精度损失会在任何操作系统和编程环境中遇到。
您可能混合了浮点数和双精度浮点数类型请确定您在进行数学运算的时候所有的数据类型全部相同。
注意:float类型的变量只有7位的精度而double类型的变量有15位的精度。
Java中的简单浮点数类型float和double不能够进行运算不光是Java,在其它很多编程语言中也有这样的问题在大多数情况下,计算的结果是准确的但昰多试几次(可以做一个循环)就可以试出类似上面的错误。现在终于理解为什么要有BCD码了
这个问题相当严重,如果你有9.元你的计算機是不会认为你可以购买10元的商品的。
在有的编程语言中提供了专门的货币类型来处理这种情况但是Java没有。现在让我们看看如何解决这個问题
现在我们已经可以解决这个问题了,原则是使用BigDecimal并且一定要用String来够造
但是想像一下吧,如果我们要做一个加法运算需要先将兩个浮点数转为String,然后够造成BigDecimal在其中一个上调用add方法,传入另一个作为参数然后把运算的结果(BigDecimal)再转换为浮点数。你能够忍受这么煩琐的过程吗下面我们提供一个工具类Arith来简化操作。它提供以下静态方法包括加减乘除和四舍五入:
* 由于Java的简单类型不能够精确的对浮点数进行运算,这个工具类提供精 * 确的浮点数运算包括加减乘除和四舍五入。 * 提供精确的加法运算 * 提供精确的减法运算。 * 提供精确嘚乘法运算 * 提供(相对)精确的除法运算,当发生除不尽的情况时精确到 * 小数点以后10位,以后的数字四舍五入 * 提供(相对)精确的除法运算。当发生除不尽的情况时由scale参数指 * 定精度,以后的数字四舍五入 * @param scale 表示表示需要精确到小数点以后几位。 * 提供精确的小数位四舍五入处理
针对double d = 2.4;
System.out.println(d);//输出2.4,却不是2.9999呢
翻阅了一些资料,当单个输出double 型值时,可以正确的用 十进制显示,具体为什么,俺也似懂非懂,但进行浮点计算,浮点计算是指浮点数参与的运算,這種运算通常伴随着因为无法精确表示而进行的近似或舍入也许和Double.toString方法的 FloatingDecimal(d).toJavaFormatString()有关系
猜测大概是2.9999超出了输絀的精度所以被截取的原因吧