java1 2是否等于0_为什么0.1+0.2不等于0.3?原来编程语言是这么算的……

打开你的 Python,输入「0.1+0.2=」,结果是多少?0.30000000000000004 对不对?为什么结果不是 0.3?本文作者给出了详细的解释。

从小我们就知道 0.1 + 0.2=0.3。但是,在光怪陆离的计算世界中,运算方式却大相径庭。

我最近开始用 JavaScript 进行编码,在阅读数据类型时,我注意到 0.1 + 0.2 不等于 0.3 的奇怪行为。

我向 Stack Overflow 寻求帮助,在上面找到了一些有用的帖子。

如下图所示:

ed22ab58a0e2fa1c04fbd34845d82303.png

Stack Overflow 界面图像。

经过大量的研究和数学运算后,我得出结论,这不是错误。

这是数学运算中的浮点运算。

让我们进一步了解内在机制。

问题描述:

为什么 0.1 + 0.2 = 0.30000000000000004?

如果你用 Java 或 C 语言编过程,那你一定知道用于存储值的不同数据类型。

我们在前面的讨论中将考虑两种数据类型:

整数型和浮点型。

整数型存储整数,而浮点型存储小数。

在这之前,我们先来了解一个小概念:

为了实现计算,数字是如何表示的?

极小数和极大数通常用科学计数法表示,即:

41f4cf561b8baa8bd342ffd046b2dcb3.png

同样,如果一个用科学计数法书写的数字小数点前有一个非零的十进制数,则该数字是标准化写法。

例如,0.0005606 用科学计数法的标准化写法为:

72f50a4a0f3972c1baac4aae0f5146dd.png

Significant 是指不包含零的有效数字,base 表示所使用的进制——此处为十进制(10)。

Exponent(指数)表示小数点需要向左或向右移动的步数。

现在,有两种显示浮点数的方法:

单精度和双精度。

在进行浮点运算时,单精度使用 32 位,而双精度使用 64 位。

与许多其他编程语言不同,JavaScript 并未定义不同类型的数字数据类型,而是始终遵循国际 IEEE 754 标准,将数字存储为双精度浮点数。

这种格式以 64 位存储数字,其中数字(分数)存储在位 0 到 51 中,指数存储在位 52 到 62 中,符号存储在位 63 中。

bd9da8bc42359af65e7698f377598d83.png

IEEE754 双精度标准。

我们按 IEEE754 标准用 64 位表示 0.1。

第一步是将十进制的 0.1 转换为二进制的 0.1。

首先将 0.1 乘以 2,然后将小数点前的数字分离出来,得到其相应的二进制数。

44dbd5fc36bfc41b5d838a01d4e643c5.png

重复此操作至 64 位。

然后把它们按升序排列,获取尾数,再根据双精度标准,我们将把其四舍五入到 52 位。

39db86a9f6fb4e1a6cf6fc266bab484f.png

尾数

用科学计数法表示二进制 0.1 并只保留前 52 位:

3144a5a50ab4bae754e032b6547951de.png

尾数部分处理好后。

现在我们用下面的方式处理指数:

9c3ab72cb05ed27827996154cd275c4d.png

这里,11 代表我们要使用的 64 位表示的指数位数,-4 代表科学计数中的指数。

所以最终数字 0.1 的表示形式是:

e6e46f3e162f8f0d686bdb37e0a4b0ca.png

同理,0.2 表示为:

dce563d6858205b246dea3b6e8ebb7d3.png

将两个数相加,得到:

682ee6da4029418a59e880443d95c0d1.png

转换为浮点数,它变成:

5f348a14a57be9bd8926015c03b26fd8.png

这就是 0.1 + 0.2 = 0.30000000000000004 的原因。

【编辑推荐】

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值