为什么 parseInt(8,3) == NaN 和 parseInt(16,3) == 1?

2022-01-17 00:00:00 numbers javascript parseint radix

我正在阅读

为什么是 parseInt(8, 3)NaNparseInt(16, 3)1?

AFAIK 8 和 16 不是 base-3 数字,因此 parseInt(16, 3) 也应该返回 NaN

解决方案

这是人们经常遇到的问题,即使他们知道.:-) 你看到这个的原因与 parseInt("1abc") 返回 1 的原因相同:parseInt 在第一个无效字符处停止并返回它在该点的任何内容.如果没有要解析的有效字符,则返回 NaN.

parseInt(8, 3) 表示以 3 为基数解析 "8""(注意它将数字 8 转换为字符串;规范中的详细信息).但在基数 3 中,个位数只是 012.这就像要求它以八进制解析 "9" .由于没有没有个有效字符,你得到了NaN.

parseInt(16, 3) 要求它以基数 3 解析 "16".由于它可以解析 1,它确实,然后它停在 6 因为它无法解析它.所以它返回 1.

<小时>

由于这个问题引起了很多关注,并且可能在搜索结果中排名很高,因此这里列出了在 JavaScript 中将字符串转换为数字的选项,以及它们的各种特性和应用程序(摘自我在 SO 上的另一个答案):

  • parseInt(str[, radix]) - 尽可能多地将字符串的开头转换为一个整数(整数),忽略末尾的额外字符.所以 parseInt("10x")10;x 被忽略.支持可选的基数(数字基数)参数,因此 parseInt("15", 16)21 (15 为十六进制).如果没有基数,则假定为十进制,除非字符串以 0x(或 0X)开头,在这种情况下,它会跳过这些并假定为十六进制.(某些浏览器过去会将以 0 开头的字符串视为八进制;这种行为从未指定过,并且是 在 ES5 规范中明确禁止.)如果没有找到可解析的数字,则返回 NaN.

  • parseFloat(str) - 与 parseInt 类似,但处理浮点数且仅支持十进制.字符串上的额外字符再次被忽略,因此 parseFloat("10.5x")10.5 (x 被忽略).由于仅支持十进制,parseFloat("0x15")0(因为解析在 x 处结束).如果没有找到可解析的数字,则返回 NaN.

  • 一元+,例如+str - (例如,隐式转换) 使用浮点数和 JavaScript 的标准数字表示法将 整个 字符串转换为数字(只有数字和小数点 = 十进制; 0x 前缀 = 十六进制; 0o 前缀 = 八进制 [ES2015+]; 一些 实现扩展它以处理前导 0 为八进制,但不是严格模式).+"10x"NaN 因为 x 不 被忽略.+"10"10+"10.5"10.5+"0x15"21+"0o10"8 [ES2015+].有一个陷阱:+""0,而不是您可能期望的 NaN.

  • Number(str) - 完全像隐式转换(例如,像上面的一元 +),但在某些实现上速度较慢.(这可能并不重要.)

I'm reading this but I'm confused by what is written in the parseInt with a radix argument chapter

Why is it that parseInt(8, 3)NaN and parseInt(16, 3)1?

AFAIK 8 and 16 are not base-3 numbers, so parseInt(16, 3) should return NaN too

解决方案

This is something people trip over all the time, even when they know about it. :-) You're seeing this for the same reason parseInt("1abc") returns 1: parseInt stops at the first invalid character and returns whatever it has at that point. If there are no valid characters to parse, it returns NaN.

parseInt(8, 3) means "parse "8" in base 3" (note that it converts the number 8 to a string; details in the spec). But in base 3, the single-digit numbers are just 0, 1, and 2. It's like asking it to parse "9" in octal. Since there were no valid characters, you got NaN.

parseInt(16, 3) is asking it to parse "16" in base 3. Since it can parse the 1, it does, and then it stops at the 6 because it can't parse it. So it returns 1.


Since this question is getting a lot of attention and might rank highly in search results, here's a rundown of options for converting strings to numbers in JavaScript, with their various idiosyncracies and applications (lifted from another answer of mine here on SO):

  • parseInt(str[, radix]) - Converts as much of the beginning of the string as it can into a whole (integer) number, ignoring extra characters at the end. So parseInt("10x") is 10; the x is ignored. Supports an optional radix (number base) argument, so parseInt("15", 16) is 21 (15 in hex). If there's no radix, assumes decimal unless the string starts with 0x (or 0X), in which case it skips those and assumes hex. (Some browsers used to treat strings starting with 0 as octal; that behavior was never specified, and was specifically disallowed in the ES5 specification.) Returns NaN if no parseable digits are found.

  • parseFloat(str) - Like parseInt, but does floating-point numbers and only supports decimal. Again extra characters on the string are ignored, so parseFloat("10.5x") is 10.5 (the x is ignored). As only decimal is supported, parseFloat("0x15") is 0 (because parsing ends at the x). Returns NaN if no parseable digits are found.

  • Unary +, e.g. +str - (E.g., implicit conversion) Converts the entire string to a number using floating point and JavaScript's standard number notation (just digits and a decimal point = decimal; 0x prefix = hex; 0o prefix = octal [ES2015+]; some implementations extend it to treat a leading 0 as octal, but not in strict mode). +"10x" is NaN because the x is not ignored. +"10" is 10, +"10.5" is 10.5, +"0x15" is 21, +"0o10" is 8 [ES2015+]. Has a gotcha: +"" is 0, not NaN as you might expect.

  • Number(str) - Exactly like implicit conversion (e.g., like the unary + above), but slower on some implementations. (Not that it's likely to matter.)

相关文章