• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

javascript为什么0.1+0.2=0.30000000000000004

武飞扬头像
正经程序员
帮助18

前言

新手在学习JavaScript时,初次看到这个问题都会去控制台试试,0.1 0.2=?,得到的结果如下:

这个错误的根本原因是:大多数十进制无法正确的转换为二进制。

在计算机上计算时,是将十进制转换为二进制后进行计算,并将计算结果从二进制转换为十进制再次显示。不仅是JavaScript,其他语言如python也是如此。

在JavaScript中主要是因为 Number 类型遵循的是 IEEE 754 标准,使⽤的是 64 位固定⻓度来表示。

IEEE 754 浮点数由三个域组成,分别为 sign bit (符号位)、exponent bias (指数偏移值) 和 fraction (分数值)。64 位中,

sign bit 占 1 位,exponent bias 占 11 位,fraction 占 52 位。

通过公式表示浮点数的值 value = sign x exponent x fraction

当⼀个数为正数,sign bit 为 0,当为负数时,sign bit 为 1.

以 0.1 转换为 IEEE 754 标准表示为例解释⼀下如何求 exponent bias 和 fraction。转换过程主要经历 3 个过程:

  1. 将 0.1 转换为⼆进制表示
  2. 将转换后的⼆进制通过科学计数法表示
  3. 将通过科学计数法表示的⼆进制转换为 IEEE 754 标准表示

将0.1转换为二进制表示

在大学期间学习进制转换时,我们都学过如何转二进制,下面是⼀个数的⼩数部分如何转换为⼆进制。⼀个数的⼩数部分,乘以 2,然后取整数部分的结果,再⽤计算后的⼩数部分重复计算,直到⼩数部分为 0 。

因此 0.1 转换为⼆进制表示的过程如下:

小数 x2的结果 整数部分
0.1 0.2 0
0.2 0.4 0
0.4 0.8 0
0.8 1.6 1
0.6 1.2 1
0.2 0.4 0
0.4 0.8 0
0.8 1.6 1
... ... ...

所以得到 0.1 的⼆进制表示为 0.00011...(⽆限重复 0011) 。

将转换后的二进制通过科学计数法表示

0.00011...(⽆限重复 0011) 通过科学计数法表示则是 1.10011001...(⽆限重复 1001)*2

转换为 IEEE 754 标准表示

当经过科学计数法表示之后,就可以求得 exponent bias 和 fraction 了。

exponent bias (指数偏移值) 等于 双精度浮点数固定偏移值 (2-1) 加上指数实际值(即 2 中的 -4) 的 11 位⼆进制表示。

为什么是 11 位?因为 exponent bias 在 64 位中占 11 位。

因此 0.1 的 exponent bias 等于 1023 (-4) = 1019 的11 位⼆进制表示,即 011 1111 1011。

再来获取 0.1 的 fraction,fraction 就是 1.10011001...(⽆线重复 1001) 中的⼩数位,由于 fraction 占 52位所以抽取 52

位⼩数,1001...(中间有 11 个 1001)...1010 (请注意最后四位,是 1010 ⽽不是 1001,因为四舍五⼊有进位,这个进位

就是造成 0.1 0.2 不等于 0.3 的原因)

0 011 1111 1011 1001...( 11 x 1001)...1010

(sign bit) (exponent bias) (fraction)

此时如果将这个数转换为⼗进制,可以发现值已经变为 0.100000000000000005551115123126 ⽽不是 0.1 了,因此这个计算精度就出现了问题。

如何避免这个问题

在 JavaScript 中避免此错误的唯一方法是四舍五入到所需的小数位数。

如果小数点为一位,则将其乘以 10(如果是两位则为 100),然后将其四舍五入,然后将四舍五入的值除以 10。

var a = 0.1   0.2; // 0.30000000000000004

a = Math.round (a * 10); // 乘以 10 → 舍入 "3.0000000000000004" → "3"
a = a / 10; // “3”除以 10
console.log (a); // 0.3

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanfbebk
系列文章
更多 icon
同类精品
更多 icon
继续加载