【问题标题】:Getting NaN inconsistently mapping parseInt获取 NaN 不一致地映射 parseInt
【发布时间】:2015-11-26 03:27:34
【问题描述】:

正在使用一些代码来创建0 的数组,发现只返回一个值NaN 而不是0。我在 Chrome、Node 和 Firefox 中得到了这个。

是什么导致第二个值是NaN

var arr = new Array(32).join(0).split('').map(parseInt)
// prints [0, NaN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
console.dir(arr)

【问题讨论】:

标签: javascript arrays nan


【解决方案1】:

.map() 函数将 三个 参数传递给回调,parseInt() 使用其中两个参数:值和索引(第三个是数组本身)。当索引为1 时,任何数字字符串都将是无效值。 parseInt() 函数在第二个参数为 0 时会忽略它。

详细说明:对于第一个元素,parseInt() 是这样调用的:

parseInt("0", 0)

因为数组值为零,索引为零。在第二次通话中,是这样的:

parseInt("0", 1)

然后返回NaN

请注意,如果您对所有整数的结果不太挑剔,您可以使用 Number 构造函数做您想做的事情:

var arr = new Array(32).join(0).split('').map(Number);

在 ES2015(最新批准的 JavaScript 标准,如果我们都非常好,它将作为我们的圣诞礼物在所有浏览器中完全实现)你可以使用 .fill() 函数:

var arr = new Array(31).fill(0);

【讨论】:

  • Three arguments,第三个是您要映射的数组。 parseInt 忽略第三个。
  • @user2357112 是的,这是真的,是的,parseInt 只查看它的前两个参数。
【解决方案2】:

映射将三个参数传递给它的函数:

  • 元素;
  • 该元素在数组中的索引;和
  • 数组本身。

parseInt 函数将查看其中的前两个,将第一个正确视为字符串,但将第二个视为要使用的基础。当基数既不为零也不在包含范围2..36 中时,它返回NaN (1)。如果您有一个包含 40 个元素的数组,您还会在末尾看到一堆 NaN 值:

0, NaN, 0, 0, 0, ... 0, 0, 0, NaN, NaN

如果数字字符串不是零,您还会得到一些非常奇怪的结果,因为数组索引将决定使用什么基数来解释它。

要真正修复这个问题,您只需提供一个函数,将map 给您的内容转换为parseInt 期望 (地图,我猜你可以这么称呼它):

function myParseInt(s,r,a) { return parseInt(s,10); }
var arr = new Array(32).join(0).split('').map(myParseInt)
alert(arr)

你可能还想看看你创建这个数组的方式,它实际上最终会是一个大小为 31 而不是 32 的数组。如果你只想要一个 '0' 字符的数组,你可以只需使用:

var arr = new Array(32).fill('0')

假设您有一个支持 ECMAScript 2015 的浏览器,截至本答案发布时,它是 Safari、Firefox 和 Chrome-desktop。


(1) 以 0 为底是处理十六进制前缀之类的默认情况。

在纯位置系统(每个数字乘以基数的幂并累加)中,1 的基数没有意义,因为唯一允许的数字是0,所以每个位值都是零乘以1<sup>n</sup>。换句话说,在以一为基数的系统中唯一可能的数字是零。

因此,从 236 的基数更合理。

【讨论】:

  • 你说基数 1 不可行,因为唯一的数字是 1^n,实际上基数 1 的位数与数字一样多(即 30 = 1.......1 三十次)。以 1 为基数的操作非常长,尤其是打印以 1 为基数的数字可能需要打印大量的数字,而这些数字信息量不是很大。这当然是一个约定,也有需要证明以 1 为底的定理(即 3 个寄存器的机器是图灵完备的)
  • @DarioOO,base 1 只有数字 0(不是 1),就像 base 2 只有 01。在纯粹的位置系统中,0 只能生成零,因为来自给定位置n 的值将是0 x 1^n。换句话说,00000...000 是零,无论您有 多少 个数字。基数 1 对于非位置系统可能是可行的,但我会明确表示这就是我的意思。
  • 那是因为你扩展了一个适用于 base2+ 数字的定义,它通常是一个由 1 而非 0 组成的数字:en.wikipedia.org/wiki/Unary_numeral_system 它不是数字基数的唯一定义,存在具有一元基数的一般定义。
【解决方案3】:

这是因为传递给map 的函数将使用三个参数调用:

  1. 当前数组项
  2. 该项的索引
  3. 整个数组

在这种情况下,该函数是parseInt,它只使用两个参数:

  1. 要解析的字符串
  2. 用于解析字符串的基数
  3. 其他参数将被忽略。

因此,对于数组中的第二项(即索引1),调用将是

parseInt("0", 1, ignoredArray)

当基数为1时,返回NaN

  • R = ToInt32(radix)。
  • 如果 R ≠ 0,则
    • 如果 R R > 36,则返回 NaN

另请注意,如果您使用更大的数字,例如 new Array(99),您会看到 NaNs 从索引 37 开始。

【讨论】:

  • 然而 0 是一个有效的基数?
  • 如果确实需要解析一个整数字符串数组,最简单的解决方案是使用parseFloat,它只需要一个参数。
  • @immibis 在数学上,0 基数没有意义。因此,如果你使用 0,JS 会假设你的意思是 10。
猜你喜欢
  • 2014-12-02
  • 1970-01-01
  • 2021-09-12
  • 2016-05-20
  • 1970-01-01
  • 2017-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多