hun*_*eox 4 javascript ieee-754
如果我理解正确的话,JavaScript 数字总是按照国际 IEEE 754 标准存储为双精度浮点数。这意味着它使用 52 位作为小数有效数。但是在上图中,二进制中的 0.57 似乎使用了 54 位。
另一件事是(如果我理解正确的话)二进制 0.55 也是一个重复数字。但为什么0.55 + 1 = 1.55(没有损失)和0.57 + 1 = 1.5699999999999998
这意味着它使用 52 位作为小数有效数。但是在上图中,二进制中的 0.57 似乎使用了 54 位。
JavaScript 的Number类型本质上是 IEEE 754 基本 64 位二进制浮点数,具有 53 位有效数。52 位编码在“尾随有效数”字段中。前导位通过指数字段进行编码(1-2046 的指数字段表示前导位为 1,指数字段 0 表示前导位为零,2047 的指数字段用于无穷大或 NaN)。
您看到的 0.57 的值有 53 个有效位。领先的“0”。由toString操作产生;它不是数字编码的一部分。
但是为什么 0.55 + 1 = 1.55(没有损失)和 0.57 + 1 = 1.5699999999999998。
当 JavaScript 格式化一些Number x以使用其默认规则显示时,这些规则说产生最短的十进制数字(在其有效数字中,不计算像前导“0”这样的装饰。)当转换回Number格式时,产生x . 此规则的目的包括 (a) 始终确保显示唯一标识哪个确切Number值是源值和 (b) 不使用超过完成 (a) 所需的数字。
因此,如果您以十进制数字(例如 .57 )开头并将其转换为 a Number,则会得到一些值x,这是转换必须四舍五入为Number格式中可表示的数字的结果。然后,当x被格式化以供显示时,您将获得原始数字,因为产生最短数字并转换回x 的规则自然会产生您开始使用的数字。
(但x并不完全代表 0.57。最接近double0.57 的值略低于它;在 IEEEdouble计算器上查看它的十进制和二进制 64 表示)。
另一方面,当您执行诸如 之类的操作时.57 + 1,您正在执行一些算术运算,生成的数字y并非以简单的十进制数字开头。因此,在格式化此类数字以供显示时,规则可能需要使用更多数字。换句话说。添加.57and 时1,Number格式中的结果与从 中得到的数字不同1.57。因此,为了格式化 的结果.57 + 1,JavaScript 必须使用更多的数字来区分该数字和您从中获得的数字1.57——它们是不同的,必须以不同的方式显示。
如果0.57是一个精确表示double,和的预取整的结果会完全1.57,所以1 + 0.57将四舍五入到相同double的1.57。
但事实并非如此,实际上是1 + nearest_double(0.57)=
1.569999999999999951150186916493(预舍入,而不是 a double) 向下舍入为
1.56999999999999984012788445398. 这些数字的十进制表示比我们需要区分有效数的 1ulp(最后一位单位),甚至 0.5 ulp 最大舍入误差所需的位数多得多。
1.57舍入到 ~ 1.5700000000000006217248937901,因此这不是打印1 + 0.57. 十进制字符串需要将数字与相邻的 binary64 值区分开来。
碰巧发生在 中的舍入.55 + 1产生与转换1.55为相同的数字Number,因此显示的结果.55 + 1产生“1.55”。
| 归档时间: |
|
| 查看次数: |
4208 次 |
| 最近记录: |