为什么 JavaScript 的 parseInt(0.0000005) 打印“5”?
Why does JavaScript's parseInt(0.0000005) print "5"?
我读过一篇关于 JavaScript parseInt
的文章,其中有这个问题:
parseInt(0.5); // => 0
parseInt(0.05); // => 0
parseInt(0.005); // => 0
parseInt(0.0005); // => 0
parseInt(0.00005); // => 0
parseInt(0.000005); // => 0
parseInt(0.0000005); // => 5
为什么会这样?
我在 ecmascript standard 上搜索过它,看到了这个:
第一步是converting the input to `string` if it is not
:
19.2.5 parseInt ( string, radix )
The parseInt function is the %parseInt% intrinsic object. When the parseInt function is called, the following steps are taken:
Let inputString be ? ToString(string).
- Let S be ! TrimString(inputString, start).
...
因此,我使用 String
函数检查了基于字符串的值,以查看每个值的输出:
String(0.5); // => '0.5'
String(0.05); // => '0.05'
String(0.005); // => '0.005'
String(0.0005); // => '0.0005'
String(0.00005); // => '0.00005'
String(0.000005); // => '0.000005'
String(0.0000005); // => '5e-7'
所以,这意味着当我们使用 parseInt(0.0000005)
时,它等于 parseInt('5e-7')
并且根据定义:
parseInt
may interpret only a leading portion of string as an integer value
; it ignores any code units that cannot be interpreted as part of the notation of an integer, and no indication is given that any such code units were ignored.
所以答案会 return 5
只是因为它是唯一一个在非字符 e
之前是数字的字符,所以它的其余部分 e-7
会被丢弃。
(这更像是一个长评论,而不是一个竞争性的答案。)
导致这种奇怪效果的不需要的转换仅在将值作为数字类型传递给 parseInt
时发生 - 在这种情况下,编译器(或解释器或任何驱动 JS 的东西)似乎 auto-converts 为您将数字转换为字符串,因为字符串类型是函数参数的预期类型
不幸的是,number-to-string 转换函数更喜欢工程编号格式,否则它会变得太长。
此外,转换可能会导致精度损失,这是每个程序员在处理十进制 (non-integer) 数字时都必须注意的事情。
如果您记得自己将 to-be-parsed 值放入字符串中,那么您就不会得到这样意想不到的结果:
let n = '0.0000005';
console.log(parseInt(n))
将根据需要打印 0。
经验教训:
- 尽可能避免隐式类型转换。
- 避免使用
parseInt
和类似的函数,它们不会让您知道要解析的字符串是否有额外的 non-fitting 数据。例如,int-parsing "x" 或 "1x" 都应该告诉你这不是一个正确的整数。在这方面,parseInt
通过忽略字符串中的额外数据而不告诉我们来表现出不良行为。一个好的解析器函数要么告诉你它在哪里停止(这样你就可以检查是否有垃圾遗留下来),要么在它发现意外数据时失败。
请尊重数据类型!
在 Chrome 控制台中:
parseInt("0.5");
0
parseInt("0.05");
0
parseInt("0.005");
0
parseInt("0.0005");
0
parseInt("0.00005");
0
parseInt("0.000005");
0
parseInt("0.0000005");
0
parseInt("0.00000005");
0
parseInt("0.000000005");
0
我读过一篇关于 JavaScript parseInt
的文章,其中有这个问题:
parseInt(0.5); // => 0
parseInt(0.05); // => 0
parseInt(0.005); // => 0
parseInt(0.0005); // => 0
parseInt(0.00005); // => 0
parseInt(0.000005); // => 0
parseInt(0.0000005); // => 5
为什么会这样?
我在 ecmascript standard 上搜索过它,看到了这个:
第一步是converting the input to `string` if it is not
:
19.2.5 parseInt ( string, radix )
The parseInt function is the %parseInt% intrinsic object. When the parseInt function is called, the following steps are taken:
Let inputString be ? ToString(string).
- Let S be ! TrimString(inputString, start).
...
因此,我使用 String
函数检查了基于字符串的值,以查看每个值的输出:
String(0.5); // => '0.5'
String(0.05); // => '0.05'
String(0.005); // => '0.005'
String(0.0005); // => '0.0005'
String(0.00005); // => '0.00005'
String(0.000005); // => '0.000005'
String(0.0000005); // => '5e-7'
所以,这意味着当我们使用 parseInt(0.0000005)
时,它等于 parseInt('5e-7')
并且根据定义:
parseInt
may interpretonly a leading portion of string as an integer value
; it ignores any code units that cannot be interpreted as part of the notation of an integer, and no indication is given that any such code units were ignored.
所以答案会 return 5
只是因为它是唯一一个在非字符 e
之前是数字的字符,所以它的其余部分 e-7
会被丢弃。
(这更像是一个长评论,而不是一个竞争性的答案。)
导致这种奇怪效果的不需要的转换仅在将值作为数字类型传递给 parseInt
时发生 - 在这种情况下,编译器(或解释器或任何驱动 JS 的东西)似乎 auto-converts 为您将数字转换为字符串,因为字符串类型是函数参数的预期类型
不幸的是,number-to-string 转换函数更喜欢工程编号格式,否则它会变得太长。
此外,转换可能会导致精度损失,这是每个程序员在处理十进制 (non-integer) 数字时都必须注意的事情。
如果您记得自己将 to-be-parsed 值放入字符串中,那么您就不会得到这样意想不到的结果:
let n = '0.0000005';
console.log(parseInt(n))
将根据需要打印 0。
经验教训:
- 尽可能避免隐式类型转换。
- 避免使用
parseInt
和类似的函数,它们不会让您知道要解析的字符串是否有额外的 non-fitting 数据。例如,int-parsing "x" 或 "1x" 都应该告诉你这不是一个正确的整数。在这方面,parseInt
通过忽略字符串中的额外数据而不告诉我们来表现出不良行为。一个好的解析器函数要么告诉你它在哪里停止(这样你就可以检查是否有垃圾遗留下来),要么在它发现意外数据时失败。
请尊重数据类型!
在 Chrome 控制台中:
parseInt("0.5");
0
parseInt("0.05");
0
parseInt("0.005");
0
parseInt("0.0005");
0
parseInt("0.00005");
0
parseInt("0.000005");
0
parseInt("0.0000005");
0
parseInt("0.00000005");
0
parseInt("0.000000005");
0