【问题标题】:Why does JavaScript's parseInt(0.0000005) print "5"?为什么 JavaScript 的 parseInt(0.0000005) 打印“5”?
【发布时间】:2021-12-05 08:43:18
【问题描述】:

我看过一篇关于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

为什么会这样?

【问题讨论】:

  • 这个问题和答案中的某处可能应该是措辞强硬的建议,而不是parseInt(x),因为x 不是字符串。如果您已经有一个号码,大概您想要Math.round()Math.floor() 或其他东西。这里的例子表明,你经常得到看起来合理的输出本质上只是运气。
  • 虽然 ESLint 没有抱怨,但至少 PhpStorm(这对 JavaScript 和 TypeScript 也很有用)警告说一个数字不能作为字符串参数分配)。
  • 这是不检查输入值类型的常见谬误示例。这里介绍了这个和其他隐式字符串转换的例子 - alex-klaus.com/javascript-wat

标签: javascript node.js typescript type-conversion parseint


【解决方案1】:

请尊重数据类型!

在 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

【讨论】:

    【解决方案2】:

    (这更像是一个长评论,而不是一个竞争性的答案。)

    导致这种奇怪效果的不需要的转换仅在将值作为数字类型传递给 parseInt 时发生 - 在这种情况下,编译器(或解释器或任何驱动 JS 的驱动器)似乎将数字自动转换为字符串对你来说,因为字符串类型是函数参数的预期类型

    不幸的是,这个数字到字符串的转换函数更喜欢工程数字格式,否则它会变得太长。

    此外,转换可能会导致精度损失,这是每个程序员在处理十进制(非整数)数字时都必须注意的事情。

    如果您记得自己将要解析的值放入字符串中,那么您将不会得到这样的意外结果:

    let n = '0.0000005';
    console.log(parseInt(n))
    

    将根据需要打印 0。

    经验教训:

    • 尽可能避免隐式类型转换。
    • 避免使用parseInt 和不会让您知道要解析的字符串是否有额外的非拟合数据的类似函数。例如,int-parsing "x" 或 "1x" 都应该告诉你这不是一个正确的 int 数。在这方面,parseInt 通过忽略字符串中的额外数据而不告诉我们表现出不良行为。一个好的解析器函数要么告诉您它在哪里停止(以便您检查是否有剩余垃圾),要么在它发现意外数据时失败。

    【讨论】:

      【解决方案3】:

      我在ecmascript standard 上搜索过,看到了这个:

      第一步将输入转换为字符串,如果不是:

      19.2.5 parseInt(字符串,基数)

      parseInt 函数是 %parseInt% 内在对象。当调用 parseInt 函数时,会采取以下步骤:

      1. Let inputString be ? ToString(string).
      2. 让S成为!修剪字符串(输入字符串,开始)。

      ...

      所以,我检查了基于字符串的值:

      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 只能将字符串的前导部分解释为整数值;它忽略任何不能被解释为整数表示法一部分的代码单元,并且没有给出任何此类代码单元被忽略的指示。

      所以答案将返回 5 只是因为它是唯一一个直到非字符 e 的数字字符,所以其余的 e-7 将被丢弃。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-06
        • 2015-12-26
        相关资源
        最近更新 更多