快速业务通道

Java理论与实践: 您的小数点到哪里去了? - 编程入门网

作者 佚名技术 来源 NET编程 浏览 发布时间 2012-06-22

基本浮点类型和包装类浮点有不同的比较行为

使事情更糟的是,在基本 float 类型和包装类 Float 之间,用于比较 NaN 和 -0 的规则是不同的。对于 float 值,比较两个 NaN 值是否相等将会得到 false ,而使用 Float.equals() 来比较两个 NaN Float 对象会得到 true。造 成这种现象的原因是,如果不这样的话,就不可能将 NaN Float 对象用作 HashMap 中的键。类似的,虽然 0 和 -0 在表示为浮点值时,被认为是相等的 ,但使用 Float.compareTo() 来比较作为 Float 对象的 0 和 -0 时,会显示 -0 小于 0。

Java理论与实践: 您的小数点到哪里去了?(2)

时间:2010-12-22 IBM Brian Goetz

浮点中的危险

由于无穷大、NaN 和 0 的特殊行为,当应用浮点数时,可能看似无害的转换 和优化实际上是不正确的。例如,虽然好象 0.0-f 很明显等于 -f ,但当 f 为 0 时,这是不正确的。还有其它类似的 gotcha,表 2 显示了其中一些 gotcha 。

表 2. 无效的浮点假定

这个表达式…… 不一定等于…… 当……
0.0 - f -f f 为 0
f < g ! (f >= g) f 或 g 为 NaN
f == f true f 为 NaN
f + g - g f g 为无穷大或 NaN

舍入误差

浮点运算很少是精确的。虽然一些数字(譬如 0.5 )可以精确地表示为二进 制(底数 2)小数(因为 0.5 等于 2 -1),但其它一些数字(譬如 0.1 )就 不能精确的表示。因此,浮点运算可能导致舍入误差,产生的结果接近 ― 但不 等于 ― 您可能希望的结果。例如,下面这个简单的计算将得到 2.600000000000001 ,而不是 2.6 :

double s=0;   for (int i=0; i<26; i++)    s += 0.1;   System.out.println(s);

类似的, .1*26 相乘所产生的结果不等于 .1 自身加 26 次所得到的结果。 当将浮点数强制转换成整数时,产生的舍入误差甚至更严重,因为强制转换成整 数类型会舍弃非整数部分,甚至对于那些“看上去似乎”应该得到整数值的计算 ,也存在此类问题。例如,下面这些语句:

double d = 29.0 * 0.01;   System.out.println(d);   System.out.println((int) (d * 100));

将得到以下输出:

0.29   28

这可能不是您起初所期望的。

浮点数比较指南

由于存在 NaN 的不寻常比较行为和在几乎所有浮点计算中都不可避免地会出 现舍入误差,解释浮点值的比较运算符的结果比较麻烦。

最好完全避免使用浮点数比较。当然,这并不总是可能的,但您应该意识到 要限制浮点数比较。如果必须比较浮点数来看它们是否相等,则应该将它们差的 绝对值同一些预先选定的小正数进行比较,这样您所做的就是测试它们是否“足 够接近”。(如果不知道基本的计算范围,可以使用测试“abs(a/b - 1) < epsilon”,这种方法比简单地比较两者之差要更准确)。甚至测试看一个值是 比零大还是比零小也存在危险 ―“以为”会生成比零略大值的计算事实上可能 由于积累的舍入误差会生成略微比零小的数字。

NaN 的无序性质使得在比较浮点数时更容易发生错误。当比较浮点数时,围 绕无穷大和 NaN 问题,一种避免 gotcha 的经验法则是显式地测试值的有效性 ,而不是试图排除无效值。在清单 1 中,有两个可能的用于特性的 setter 的 实现,该特性只能接受非负数值。第一个实现会接受 NaN,第二个不会。第二种 形式比较好,因为它显式地检测了您认为有效

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号