Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/466.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript运行时如何将二进制(双精度浮点格式)转换回十进制_Javascript_Ieee 754 - Fatal编程技术网

JavaScript运行时如何将二进制(双精度浮点格式)转换回十进制

JavaScript运行时如何将二进制(双精度浮点格式)转换回十进制,javascript,ieee-754,Javascript,Ieee 754,给出一个十进制数字0.2 前 我假设它存储在内存中为(基于双精度64位浮点格式IEEE 754) 这个二进制数实际上是四舍五入到适合64位的 如果我们把这个值转换回十进制,我们将得到 0.19999999999999998 (0.1999999999999999833466546306226518936455249786376953125) 不完全是0.2 我的问题是,当我们询问theNumber(例如:alert(theNumber))的十进制值时,JavaScript运行时如何知道the

给出一个十进制数字0.2

我假设它存储在内存中为(基于双精度64位浮点格式IEEE 754)

这个二进制数实际上是四舍五入到适合64位的

如果我们把这个值转换回十进制,我们将得到

0.19999999999999998

(0.1999999999999999833466546306226518936455249786376953125)
不完全是0.2


我的问题是,当我们询问
theNumber
(例如:
alert(theNumber)
)的十进制值时,JavaScript运行时如何知道
theNumber
最初是0.2?

事实上,
0.2
由您发布的其他位序列表示
每次您的结果将匹配正确的位序列,console将输出
0.2
。但如果您的计算结果是其他顺序,console将输出类似于您的
0.19999999998


最常见的示例
0.1+0.2
也存在类似的情况,该示例给出了输出
0.300000000000000004
,因为该结果的位序列不同于
0.3
的表示

console.log(0.2)
控制台日志(0.05+0.15)
console.log(0.02+0.18)
console.log(0.3)
console.log(0.1+0.2)

log(0.05+0.25)
JavaScript将
数字
默认转换为字符串时,产生的小数位数刚好足以唯一区分
数字。(这源于本协议第7.1.12.1条中的步骤5,我对此进行了一些解释。)

让我们先考虑把十进制数字转换成<代码>号码<代码>。当一个数字被转换成一个

数字时,其精确的数学值被四舍五入到
数字中可表示的最接近的值。因此,当源代码中的
0.2
转换为
数字时,结果是0.200000000001110223024625156540236316680908203125

数字
转换为十进制时,我们需要生成多少位数字来唯一区分
数字
?在0.20000000000111022302462515654404236316680908203125的情况下,如果我们产生“0.2”,我们有一个十进制数字,当再次转换为
数字时,结果是0.200000000001110223024625156404236680908203125。因此,“0.2”唯一地将0.20000000000111022302462515654023631668090908203125与其他
Number
值区分开来,这就是我们所需要的

换句话说,JavaScript的规则是产生足够的数字来区分
数字
,这意味着任何短的十进制数字在转换为
数字
并返回到字符串时都将产生相同的十进制数字(除去不重要的零,因此“0.2000”将变为“0.2”或“045”将变为“0.2”)“45”)。(一旦十进制数字变得足够长,与
数值冲突,它可能无法在往返转换过程中继续存在。例如,“0.200000000000000003”将成为
数值
0.200000000000000003885780585618804780478148271083831787109375,然后是字符串“0.200000000000000004”。)


如果作为算术的结果,我们有一个接近0.20000000000111022302462515654023631668090908203125但不同的数字,例如0.200000000003885780586188047804780478047804780478047804780478047804780478047804780478047804780478047804780478047804780478047804780478047894781482710808083831787109375,那么JavaScript将打印更多的数字,“0.200000000000000000000004”在本例中,因为它需要更多的数字来区分“所以,我的假设是错误的

我写了一个小程序来做这个实验

进入内存的二进制值不是

0-01111111100-1001100110011001100110011001100110011001100110011001
尾数部分不是
10011001

它得到了这个值,因为我截断了该值,而不是将其舍入。:((

10011001…[1001]
需要四舍五入到52位。如果序列是1,则第53位将向上取整序列并变为:
100110011010

正确的二进制值应为:

0-01111111100-1001100110011001100110011001100110011001100110011010
该值的完整小数点为:

0.200 000 000 000 000 011 102 230 246 251 565 404 236 316 680 908 203 125
不是

正如Eric的回答,所有的十进制数,如果被转换成二进制

0-01111111100-1001100110011001100110011001100110011001100110011010

将“视”为0.2(除非我们使用toFixed()打印更多的数字);所有这些十进制数字共享相同的二进制签名(我真的不知道如何描述它).

一个有趣的问题。我从来没有想过这个问题,但JS似乎也会保持原始值。此外,如果你做了
数字+0
,你仍然会得到
0.2
,因此
+0
显然是不可行的。但是
数字+1-1
现在是不正确的,因为它使用了underyin数学运算的g值。在Chrome中,你为我得到的
0.2
值是->
00110011001
您将获得
0.20000000000111022302462515654023631668090908203125
,将+1-1作为@vlaz,然后您将获得
0.19999999999999995559107901499373838383054733276367187500
,因此在我看来,数字的默认呈现有一些标准截断,这是我无法找到的小数,它可能在规格中的某个地方。你从哪里得到了0.199999999999999983346665463062626518936455249786376953125的
0.2
?正确的值是0.200000000001110223024625165404236680908203125。谢谢,伙计们。看起来我需要读更多的规格。@eric,我以为0.2已经进入了内存。谢谢,eric。现在我读了你的回答再重复几次。谢谢,巴布。我以为0.2是进入内存的。所以,首先它被“转换”成它的真实数字形式。我要读更多的规范。等等。所以二进制是四舍五入的吗?不是被截断的吗?0.2只是人类可读的表示,事实上是所有数字
0.200 000 000 000 000 011 102 230 246 251 565 404 236 316 680 908 203 125
0.199 999 999 999 999 983 346 654 630 622 651 893 645 524 978 637 695 312 5
0-01111111100-1001100110011001100110011001100110011001100110011010