回 帖 发 新 帖 刷新版面

主题:一个关于数据计算精度的问题--似乎比较小白

最近我看到很多地方说计算机对浮点数的运算会有误差,我刚开始认为只是数据类型所能存储的数据的位数造成的这种误差,但后来发现还有一个问题,
任何一个十进制数在计算机里都是以二进制数表示的,所有的十进制整数都能精确的转换为二进制数,但小数就不一定了,比如十进制数0.1就不能精确的转换为二进制数了,那不就意味着0.1在计算机里面不能被精确的表示了吗,既然是这样,那对于0.1的计算,比如0.1+0.1在计算机中应该是不能被精确计算的,但事实相反,
那计算机是怎么做到精确计算这个数的呢?
还请知道的人详解!!谢谢!

回复列表 (共3个回复)

沙发

虽然无法精确表示,但可以近似的表示。只要近似的程度足够高,计算的误差就会足够小。从而得到“正确”的结果。

在十进制情况下,对于简单的计算,如果中间结果的有效数字比最终结果的有效数字多出两位或者更多,则基本上就是正确结果了。
举例来说,1除以3再乘以3,等于多少(结果保留9位有效数字)?
计算过程:
1除以3,等于0.33333333333,(中间结果比最终结果多两位有效数字,所以总共11个3)
再乘以3,等于0.99999999999
根据四舍五入,保留9位有效数字,得到1.00000000
计算结果与数学上计算的精确结果相吻合。

十进制是如此,二进制也是类似。虽然无法保存完全精确的值,但却足够的精确,对最终结果基本没有影响。在IEEE754标准的浮点数模型中,32位的浮点数(我们用的float通常就是这种浮点数),可以正确的表示七位有效数字(十进制),而64位的浮点数(我们用的double通常就是这种浮点数)则可以正确的表示十四位有效数字(十进制)。
著名的lua脚本语言,没有int类型,所有的数字都是用C语言的double,但它照样可以进行比较精确的整数计算,原因也很明显,64位浮点数可以正确表示十四位有效数字(十进制),而一般的long只能表示十位有效数字(十进制),多出了整整四位。

需要注意的是,虽然一次计算的误差忽略,但是多次计算累积得到的误差就很可观了。比如一百万个0.1相加(等于100958.343750),与0.1乘以一百万(等于100000.000000),两者相差会很大。
浮点数计算会有一些奇怪的情况出现,比如加法、乘法可能不会精确的满足交换律、结合律,除以一个数也可能不精确的等于乘以它的倒数。a+b-b不一定精确的等于a。即使b大于零,a+b也有可能等于a。这些奇怪的情况可能导致程序计算得到错误的结果,因此,编写程序时应该尽量小心,先用数学方法把计算步骤精简一下,计算次数越少,越可能得到精确结果。

板凳


非常感谢你的讲解,谢谢了!!!

3 楼

学习了!

我来回复

您尚未登录,请登录后再回复。点此登录或注册