parseInt() parses number literals with exponent incorrectly

僤鯓⒐⒋嵵緔 提交于 2019-12-01 14:18:40

问题


I have just observed that the parseInt function doesn't take care about the decimals in case of integers (numbers containing the e character).

Let's take an example: -3.67394039744206e-15

> parseInt(-3.67394039744206e-15)
-3
> -3.67394039744206e-15.toFixed(19)
-3.6739e-15
> -3.67394039744206e-15.toFixed(2)
-0
> Math.round(-3.67394039744206e-15)
0

I expected that the parseInt will also return 0. What's going on at lower level? Why does parseInt return 3 in this case (some snippets from the source code would be appreciated)?

In this example I'm using node v0.12.1, but I expect same to happen in browser and other JavaScript engines.


回答1:


I think the reason is parseInt converts the passed value to string by calling ToString which will return "-3.67394039744206e-15", then parses it so it will consider -3 and will return it.

The mdn documentation

The parseInt function converts its first argument to a string, parses it, and returns an integer or NaN




回答2:


parseInt(-3.67394039744206e-15) === -3

The parseInt function expects a string as the first argument. JavaScript will call toString method behind the scene if the argument is not a string. So the expression is evaluated as follows:

(-3.67394039744206e-15).toString()
// "-3.67394039744206e-15"
parseInt("-3.67394039744206e-15")
// -3

-3.67394039744206e-15.toFixed(19) === -3.6739e-15

This expression is parsed as:

  • Unary - operator
  • The number literal 3.67394039744206e-15
  • .toFixed() -- property accessor, property name and function invocation

The way number literals are parsed is described here. Interestingly, +/- are not part of the number literal. So we have:

// property accessor has higher precedence than unary - operator
3.67394039744206e-15.toFixed(19)
// "0.0000000000000036739"
-"0.0000000000000036739"
// -3.6739e-15

Likewise for -3.67394039744206e-15.toFixed(2):

3.67394039744206e-15.toFixed(2)
// "0.00"
-"0.00"
// -0



回答3:


If the parsed string (stripped of +/- sign) contains any character that is not a radix digit (10 in your case), then a substring is created containing all the other characters before such character discarding those unrecognized characters.

In the case of -3.67394039744206e-15, the conversion starts and the radix is determined as base 10 -> The conversion happens till it encounters '.' which is not a valid character in base 10 - Thus, effectively, the conversion happens for 3 which gives the value 3 and then the sign is applied, thus -3.

For implementation logic - http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.2.2

More Examples -

alert(parseInt("2711e2", 16));
alert(parseInt("2711e2", 10));

TO note:

The radix starts out at base 10.

If the first character is a '0', it switches to base 8.

If the next character is an 'x', it switches to base 16.




回答4:


It tries to parse strings to integers. My suspicion is that your floats are first getting casted to strings. Then rather than parsing the whole value then rounding, it uses a character by character parsing function and will stop when it gets to the first decimal point ignoring any decimal places or exponents.

Some examples here http://www.w3schools.com/jsref/jsref_parseint.asp




回答5:


parseInt has the purpose of parsing a string and not a number:

The parseInt() function parses a string argument and returns an integer of the specified radix (the base in mathematical numeral systems).

And parseInt calls the function ToString wherein all the non numerical characters are ignored.

You can use Math.round, which also parses strings, and rounds a number to the nearest integer:

Math.round("12.2e-2") === 0 //true



回答6:


Math.round("12.2e-2") may round up or down based on the value. Hence may cause issues.

new Number("3.2343e-10") .toFixed(0) may solve the issue.



来源:https://stackoverflow.com/questions/30160919/parseint-parses-number-literals-with-exponent-incorrectly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!