面试再被问:为什么 0.1 + 0.2 ≠ 0.3?直接把面试官绕晕

AI 概述
编程中,0.1 + 0.2 ≠ 0.3,原因与二进制有关。0.1和0.2的二进制表示是无限循环的,计算机存储空间有限,故需截断,致精度丢失。实际存储时,0.1和0.2都存在微小误差,相加后误差累积,结果为0.30000000000000004。计算机通常用IEEE 754标准存小数,小数加法需统一指数后进行。0.1 + 0.2的计算涉及二进制转换、对阶、相加和规格化等步骤,最终因精度问题导致结果不等于0.3。
目录
文章目录隐藏
  1. 小数的二进制转换
  2. 计算机如何存储小数
  3. 小数的加法计算

面试再被问:为什么 0.1 + 0.2 ≠ 0.3?直接把面试官绕晕

编程界很经典的一个问题:为什么0.1 + 0.2 ≠ 0.3?面试中突然被问起,一时之间却不知道怎么回答。只记得与二进制有关,但具体是怎么来着,却有点说不清楚了。

后来查找了相关资料,才知道0.1 + 0.2 ≠ 0.3的来龙去脉。

简单来说:

  • 0.1 的二进制是:0.0001100110011…(无限循环 0011);
  • 0.2 的二进制是:0.001100110011…(无限循环 0011)。

由于计算机的存储空间有限,所以两个无限循环的二进制必须被截断存储,从而使两个数丢失了原本的精度。

  • 0.1 实际存储的值是0.1000000000000000055511151231257827021181583404541015625
  • 0.2 实际存储的值是0.200000000000000011102230246251565404236316680908203125

两数相加:

0.10000000000000000555...
+
0.20000000000000001110...
=
0.3000000000000000444...

其结果被浮点精度截断后就是:0.30000000000000004。

到这里,基本上就可以讲清楚0.1 + 0.2 ≠ 0.3的问题了。

如果还要进一步深挖,你可能还有很多疑问:

  • 小数的二进制是如何转换的?
  • 计算机是如何存储小数的?
  • 计算机是如何处理小数相加的?

小数的二进制转换

我们知道,整数的二进制表示:b * 2^(n - 1),b 表示二进制位的系数,n 表示第几位。比如十进制 6 可以表示:

6 = 1 * 2^2 + 1 * 2^1 + 0 * 2^0
  = 110

同理,小数部分的二进制表示方法类似:b * 2^(-n)。比如:0.25 可以这样表示:

0.25 = 0 * 2^-1 + 1 * 2^-2
     = 0.01

对应的二进制就是:0.01。

计算小数部分的二进制方法可以使用乘 2 取整法:

举例:0.625 的二进制:

  1. 0.625 * 2 = 1.25,整数 1,小数 0.25;
  2. 0.25 * 2 = 0.5,整数 0,小数 0.5;
  3. 0.5 * 2 = 1,整数 1,小数 0,结束。

顺序排列,就可以得到:0.101。

相同的方法就可以计算出 0.1 和 0.2 的二进制,有兴趣的话可以自行验证。

计算机如何存储小数

计算机通常都是使用 IEEE 754 标准的双精度浮点数进行小数的存储,也是就 64bit。

存储结构:

1bit    符号位
11bit   指数
52bit   尾数

实际能存储的小数的二进制尾数只有 52 位,超出后就会被截断。

所以,一个小数在计算机中其实是通过指数表示法来存储的,比如:0.625,对应的二进制是 0.101。指数表示就是:

-1^s * 1.01 * 2^-1
  • s 是符号位,0 或 1,上例中 s = 0;
  • 01 存储在尾数部分,1.不需要存储,默认隐含;
  • -1 需要加上 1023 后,以二进制形式存储在指数部分。

小数的加法计算

基于小数的存储结构,做加法运算时,必须先统一指数(也就是对阶),然后再进行二进制加法运算。

我们再来梳理一下 0.1 + 0.2 的计算过程:

1. 0.1 的二进制

0.1 = 0.0001100110011001100110011001100...
    # 实际有 52 位尾数,便于书写已省略,下同
    ≈ 1.1001100110011 × 2^-4

2. 0.2 的二进制

0.2 = 0.0011001100110011001100110011...
    ≈ 1.1001100110011 × 2^-3

3. 对阶

0.1 ≈ 0.11001100110011 × 2^-3
0.2 ≈ 1.10011001100110 × 2^-3

4. 相加

 1.10011001100110
+0.11001100110011
-----------------
10.01100110011001

结果就是:

10.01100110011001 × 2^-3

5. 规格化

小数点左移 1 位

1.001100110011001 × 2^-2

最后转换成十进制后就是0.30000000000000004(注意:上面的数据不是完整的 52 位尾数,若要验证需要使用完整的 52 位尾数进行计算)。

以上关于面试再被问:为什么 0.1 + 0.2 ≠ 0.3?直接把面试官绕晕的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。

「点点赞赏,手留余香」

11

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » 面试再被问:为什么 0.1 + 0.2 ≠ 0.3?直接把面试官绕晕

发表回复