查看原文
其他

一日一技:为什么浮点数在计算机中可能不准确?

kingname 未闻Code 2019-04-27

大多数人在小学奥数或者初中数学里面都学过如何把一个整数转换为二进制:

反复除以2,从后往前取余数。

例如:把数字247转换为二进制数:

  1. 247 / 2 = 123 余 1

  2. 123 /2 = 61 余 1

  3. 61 / 2 = 30 余 1

  4. 30 / 2 = 15 余 0

  5. 15 / 2 = 7 余 1

  6. 7 / 2 = 3 余 1

  7. 3 / 2 = 1 余 1

  8. 1 < 2,结束

把余数倒过来,就得到了: 11110111这就是247对应的二进制数。

那么一个浮点数如何转换为二进制数呢?

浮点数分为整数部分和小数部分,整数部分按整数转二进制的方法处理,小数部分按如下方法处理:

  1. 反复乘以2,取小数点左边的部分。如果乘积大于1,减1。简称:乘基取整。每次乘完以后把小数点左边的数从左到右按顺序排列。直到积为0时结束。

分别转换好以后,重新拼接起来。

例如:把0.2转换为二进制。

  1. 0.2 x 2 = 0.4,小数点左边部分为0

  2. 0.4 x 2 = 0.8,小数点左边部分为0

  3. 0.8 x 2 = 1.6,小数点左边部分为1

  4. 移除小数点左边的部分,重新变为0.6

  5. 0.6 x 2 = 1.2,小数点左边为1

  6. 移除小数点左边的部分,重新变为0.2

  7. 0.2 x 2 = 0.4,小数点左边部分为0

  8. 0.4 x 2 = 0.8,小数点左边部分为0

  9. 0.8 x 2 = 1.6,小数点左边部分为1

  10. 移除小数点左边的部分,重新变为0.6

  11. 0.6 x 2 = 1.2,小数点左边为1

  12. 移除小数点左边的部分,重新变为0.2

  13. ...

看到规律了吗?这个步骤可以无限循环下去,所以0.2对应的二进制数为: 0.00110011001100110011...

12.2转换为二进制: 1100.00110011001100110

但是计数机是不能处理无限循环数据的,所以现在的家用计算机,会把浮点数对应的二进制数保留53位,53位后面的数据直接截断。

所以,0.2对应的二进制数,在计算机中就会成为:

0.0011001100110011001100110011001100110011001100110011001100110011

此时的这个64位的二进制数,显然和原来的无限循环二进制数不一样。

所以说,浮点数转换为二进制以后,可能会不准确。

但也有例外,例如0.125:

  1. 0.125 x 2 = 0.25 小数点左边为0

  2. 0.25 x 2 = 0.5 小数点左边为0

  3. 0.5 x 2 = 1.0 小数点左边为1

  4. 1.0移除1以后成为0,0乘以任何数都为0,结束

所以0.125对应的二进制数为0.001,这是一个准确的二进制数,不是近似值。

同理,0.375对应的二进制数为0.011,也是准确的值。

关联文章:为什么你需要少看中文技术博客以及如何在Python里面精确四舍五入





文章已于修改

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存