gpt4 book ai didi

Javascript float 混淆

转载 作者:行者123 更新时间:2023-12-02 16:22:03 30 4
gpt4 key购买 nike

我遇到了一些困惑的操作。

var a = 0.1;
var b = 0.2;
var c = 0.3;

console.log(a); // 0.1
console.log(b); // 0.2
console.log(c); // 0.3

但是,

consolo.log(a+b+c) // 0.6000000000000001.

同时

console.log(a+(b+c)) // 0.6

据我了解,Javascript使用二进制 float ,因此无法准确表示0.1、0.2、0.3但是 (b+c) 两边的括号是做什么用的。这里有任何转换或四舍五入吗?

非常感谢,

最佳答案

如何定义 JavaScript 数字

JavaScript 编号以 IEEE754 表示 double 二进制 float (binary64),采用科学记数法,以2为基数。一个数字有 64 位,分为 3 部分(从高位到低位):

  • 第一位表示符号:0 - 正; 1 - 否定
  • 接下来的 11 位是指数部分
  • 最后 52 位用于尾数/小数

enter image description here

因此, float 的计算方式为:(-1) ^ 符号 * (2 ^ 指数) * 有效位数

注意:由于科学记数法的指数部分可以是正数,也可以是负数,因此二进制 64 数的实际指数值应通过减去来计算11 位指数值的指数偏差(即中间值 1023)。

该标准还定义了有效数字值在[1, 2)之间。由于有效数字部分的第一个数字始终为1,因此它是隐含的,并且没有在上图中呈现。所以,基本上有效数部分实际上有53位精度,上图中的红色部分只是尾数或小数部分。

二进制 64 格式的 0.1、0.2 和 0.3

根据标准,不难找到binary64格式的0.1、0.2和0.3(可以手动计算,也可以通过这个工具 http://bartaz.github.io/ieee754-visualization/ 计算):

0.1

0 01111111011 1001100110011001100110011001100110011001100110011010

用科学计数法来说,它是

1.1001100110011001100110011001100110011001100110011010 * 2e-4

注意:尾数部分为二进制格式,后面的数字也是同样的格式

0.2

0  01111111100 1001100110011001100110011001100110011001100110011010

用科学计数法来说,它是

1.1001100110011001100110011001100110011001100110011010 * 2e-3

0.3

0 01111111101 0011001100110011001100110011001100110011001100110011

用科学计数法来说,它是

1.0011001100110011001100110011001100110011001100110011 * 2e-2

将 2 个二进制 64 位数字相加的步骤

第 1 步 - 对齐指数

  • 移动指数较小的数字的尾数
  • 右移有效数
  • 每移动一个有效数字,指数就增加 1,直到两个指数相同
  • 移位后,尾数应向上舍入。

第 2 步 - 将尾数相加

  • 如果相加后的尾数不满足[1,2)要求,则将其移入该范围并更改指数

  • 移位后,尾数应向上舍入。

0.1 + 0.2 + 0.3 == 0.6000000000000001

如上所述,0.1 的指数为 -40.2 的指数为 -3,因此需要首先进行指数对齐:

移动 0.1
1.1001100110011001100110011001100110011001100110011010 * 2e-4

0.1100110011001100110011001100110011001100110011001101 * 2e-3

然后添加尾数

0.1100110011001100110011001100110011001100110011001101

1.1001100110011001100110011001100110011001100110011010

我们得到加起来的有效数值:

10.0110011001100110011001100110011001100110011001100111

但它不在范围[1,2)内,因此需要将其右移(向上舍入)到:

1.0011001100110011001100110011001100110011001100110100 (* 2e-2)

然后将其添加到

0.3 (1.0011001100110011001100110011001100110011001100110011 * 2e-2) 

我们得到:

10.0110011001100110011001100110011001100110011001100111 * 2e-2

同样,我们需要移位并向上取整,最终得到值:

1.0011001100110011001100110011001100110011001100110100 * 2e-1

它正是0.6000000000000001(十进制)的值

使用相同的工作流程,您可以计算 0.1 + (0.2 + 0.3)

工具

此网页http://bartaz.github.io/ieee754-visualization/帮助您快速将十进制数转换为二进制64格式,您可以用它来验证计算步骤。

如果您正在处理单精度二进制 float ,您可以引用这个工具:http://www.h-schmidt.net/FloatConverter/IEEE754.html

关于Javascript float 混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25925284/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com