前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >为什么「0.1+0.2!=0.3」,而「0.1+0.3==0.4」

为什么「0.1+0.2!=0.3」,而「0.1+0.3==0.4」

作者头像
LA0WAN9
发布2021-12-14 08:53:44
7890
发布2021-12-14 08:53:44
举报
文章被收录于专栏:火丁笔记火丁笔记

我们都知道潮汐现象,上学的时候老师多半简单解释一句「月球引力所致」就算了,而我们也都觉得自己明白了,但是凡事就怕琢磨:如果涨潮仅仅是月球对地球万有引力的作用结果的话,那么每天同一个地点,应该仅仅在距离月球最近引力最强的时候有一次涨潮才对,但是住在海边的人都知道,同一个地点,每天会有两次涨潮,为什么

我抛出这个问题并不是我转行搞物理学了,而是我发现很多司空见惯的问题,如果深究的话,你就会发现很多人根本就没搞懂。浮点数运算就是这样一个问题,每个人都知道浮点数运算有精度损失,但是为什么「0.1+0.2!=0.3」,而「0.1+0.3==0.4」:

float

除了含含糊糊的精度损失,你能给出更有营养的解释么?让我们看看到底是为什么!

首先,让我们举一个整数的例子,比如:

  • 十进制「13」:1*(10^1) + 3(10^0) = 10 + 3 = 13
  • 二进制「1101」:1*(2^3) + 1*(2^2) + 0*(2^1) + 1*(2^0) = 8 + 4 + 0 + 1 = 13

接着,让我们再举一个小数的例子,比如:

  • 十进制「0.625」:6*(10^-1) + 2*(10^-2) + 5*(10^-3) = 0.625
  • 二进制「0.101」:1*(2^-1) + 0*(2^-2) + 1*(2^-3) = 5/8 = 0.625

最重要的一点是你要明白计算机是如何表示小数的:比如二进制的「0.1111111」,无非就是十进制的「1/2 + 1/4 + 1/8 + 1/16 + 1/32 + 1/64 + 1/128」,不过细心的你可能已经发现问题了,计算机这种处理小数的方式存在精度损失的,比如一个十进制的「0.1」,换算成分数的话就是十进制的「1/10」,对比前面的结果,你会发现计算机没办法精确表示它,只能近似等于二进制的「0.00011」,也就是十进制的「1/16 + 1/32 = 3/32」,当然二进制小数点后可以多取几位,可惜结果是只能无限趋近,但永远不可能等于。

下面看看为什么「0.1 + 0.2 != 0.3」,而「0.1 + 0.3 == 0.4」。既然存在精度损失,那么「0.1 + 0.2 != 0.3」也说得过去,我们推算一下为什么「0.1 + 0.3 == 0.4」:

  • 十进制的「0.1」近似等于二进制「0.00011」
  • 十进制的「0.3」近似等于二进制「0.01001」
  • 十进制的「0.4」近似等于二进制「0.01100」

于是,十进制的「0.1 + 0.3」也就是二进制的「0.00011 + 0.01001」:

代码语言:javascript
复制
  0.00011
+ 0.01001
---------
  0.01100

不多不少,答案正好是 0.4!也就是说,虽然有精度损失,但是刚刚好碰巧抵消了彼此的误差。希望大家阅读完本文之后,能够彻底搞清楚浮点数运算的相关问题,如果还有不清楚的地方,推荐阅读:IEEE 754 和 THE FLOATING-POINT GUIDE

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-08-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档