528

How do parseInt() and Number() behave differently when converting strings to numbers?

1

11 Answers 11

655

Well, they are semantically different, the Number constructor called as a function performs type conversion and parseInt performs parsing, e.g.:

// parsing:
parseInt("20px");       // 20
parseInt("10100", 2);   // 20
parseInt("2e1");        // 2

// type conversion
Number("20px");       // NaN
Number("2e1");        // 20, exponential notation

Also parseInt will ignore trailing characters that don't correspond with any digit of the currently used base.

The Number constructor doesn't detect implicit octals, but can detect the explicit octal notation:

Number("010");         // 10
Number("0o10")         // 8, explicit octal

parseInt("010");       // 8, implicit octal
parseInt("010", 10);   // 10, decimal radix used

And it can handle numbers in hexadecimal notation, just like parseInt:

Number("0xF");   // 15
parseInt("0xF"); //15

In addition, a widely used construct to perform Numeric type conversion, is the Unary + Operator (p. 72), it is equivalent to using the Number constructor as a function:

+"2e1";   // 20
+"0xF";   // 15
+"010";   // 10
Sign up to request clarification or add additional context in comments.

13 Comments

Interesting, does parseInt ignore any characters trailing the number? Because in my case I would prefer getting a NaN instead of the 20 when converting.
Yes it does. Sounds like you definitely want Number()
Thank you for this. This is the first time I've seen NaN. It may be helpful for some folks to know that NaN is tested with the function isNaN ( value ). Just using "if ( value == NaN )", for example, won't work.
Number() does deal with octals much like hex and binary: Number('0o10') == 8
parseInt("010") returns 10 in Chrome
|
40

One minor difference is what they convert of undefined or null,

Number() Or Number(null) Or Number('') // returns 0

while

parseInt() Or parseInt(null) Or parseInt('') // returns NaN

1 Comment

That’s because ToNumber (null) is specified to return 0. parseInt, however expects strings, so null and undefined are coerced to the strings "null" or "undefined", respectively, first, which don’t start with digits. Number(undefined) is NaN, not 0, which is a special step of the Number() algorithm. At any rate, the question asked about “when converting strings to numbers”, not about these special cases.
35
typeof parseInt("123") => number
typeof Number("123") => number
typeof new Number("123") => object (Number primitive wrapper object)

first two will give you better performance as it returns a primitive instead of an object.

7 Comments

new Number() is different to Number(). typeof Number("123") => number
Also new Number("1") != new Number("1"). NEVER USE new Number. Never never never never. Number("1"), on the other hand, is perfectly reasonable.
@Kragen, it'd be much more beneficial to the community if you explained WHY you shouldn't use "new Number" -- instead of just typing "never" 5 times...
@ken Very old comment but for future visitors I imagine its because exactly the reason they mentioned to begin with. I parse two numbers let x = new Number("2"); let y = new Number("2"); and then later on do an equality check for whatever reason, if (x == y) { doSomething(); } logically doSomething should be called. But it wont. Also if you were to parse only one number let x = new Number("2"); then x === 2 would be false. That is a clear reason why you should not use new Number
@TomC You're seeing the result of an edited comment (that's what the pencil icon following the comment denotes); previously there was zero explanation, just strong admonition.
|
20

Summary:

parseInt():

  • Takes a string as a first argument, the radix (An integer which is the base of a numeral system e.g. decimal 10 or binary 2) as a second argument
  • The function returns a integer number, if the first character cannot be converted to a number NaN will be returned.
  • If the parseInt() function encounters a non numerical value, it will cut off the rest of input string and only parse the part until the non numerical value.
  • If the radix is undefined or 0, JS will assume the following:
    • If the input string begins with "0x" or "0X", the radix is 16 (hexadecimal), the remainder of the string is parsed into a number.
    • If the input value begins with a 0 the radix can be either 8 (octal) or 10 (decimal). Which radix is chosen is depending on JS engine implementation. ES5 specifies that 10 should be used then. However, this is not supported by all browsers, therefore always specify radix if your numbers can begin with a 0.
    • If the input value begins with any number, the radix will be 10

Number():

  • The Number() constructor can convert any argument input into a number. If the Number() constructor cannot convert the input into a number, NaN will be returned.
  • The Number() constructor can also handle hexadecimal number, they have to start with 0x.

Example:

console.log(parseInt('0xF', 16));  // 15

// z is no number, it will only evaluate 0xF, therefore 15 is logged
console.log(parseInt('0xFz123', 16));

// because the radix is 10, A is considered a letter not a number (like in Hexadecimal)
// Therefore, A will be cut off the string and 10 is logged
console.log(parseInt('10A', 10));  // 10

// first character isnot a number, therefore parseInt will return NaN
console.log(parseInt('a1213', 10));


console.log('\n');


// start with 0X, therefore Number will interpret it as a hexadecimal value
console.log(Number('0x11'));

// Cannot be converted to a number, NaN will be returned, notice that
// the number constructor will not cut off a non number part like parseInt does
console.log(Number('123A'));

// scientific notation is allowed
console.log(Number('152e-1'));  // 15.21

Comments

16

If you are looking for performance then probably best results you'll get with bitwise right shift "10">>0. Also multiply ("10" * 1) or not not (~~"10"). All of them are much faster of Number and parseInt. They even have "feature" returning 0 for not number argument. Here are Performance tests.

8 Comments

The speed of the various approaches appears to change with browser revisions over time. The linked test also has changed, and the latest version as of this comment is here - jsperf.com/number-vs-parseint-vs-plus/39 - fortunately the site contains previous versions of the test as well
Always prefer code clarity over "useless" optimizations. For most use cases parseInt or Number are more preferable. If you are programming a N64 emulator with millions of conversions per seconds, you might consider those tricks.
Question is about behavior, discussion of performance is off-topic.
Note that this can't be used for large integers -- specifically integers that don't fit in a signed 32-bit integer -- because in JavaScript, bitwise operators treat their operands as a sequence of 32 bits, rather than as decimal, hexadecimal, or octal numbers. Hence (2**31).toString() >> 0 will overflow to -2147483648. You can use >>> instead of >> to have JavaScript treat the operand as an unsigned 32-bit integer, but then any numbers larger than 2**32 - 1 will also overflow.
I tried it today and found that Number was ahead of bitwise and *1, ~~"10" had a way lower score for me.
|
15

I found two links of performance compare among several ways of converting string to int.

    parseInt(str,10)    
    parseFloat(str)
    str << 0
    +str
    str*1 
    str-0
    Number(str)

enter image description here http://jsben.ch/#/zGJHM

enter image description here enter image description here http://phrogz.net/js/string_to_number.html

Comments

8

parseInt() -> Parses a number to specified redix.

Number()-> Converts the specified value to its numeric equivalent or NaN if it fails to do so.

Hence for converting some non-numeric value to number we should always use Number() function.

eg.

Number("")//0
parseInt("")//NaN

Number("123")//123
parseInt("123")//123

Number("123ac") //NaN,as it is a non numeric string
parsInt("123ac") //123,it parse decimal number outof string

Number(true)//1
parseInt(true) //NaN

There are various corner case to parseInt() functions as it does redix conversion, hence we should avoid using parseInt() function for coersion purposes.

Now, to check weather the provided value is Numeric or not,we should use nativeisNaN() function

2 Comments

parseInt() only parses a number out of a string that contains letters if the number part comes first
"it parse decimal number" parseInt() parses the integer, leaves the decimal part, for example parseInt('1.1') returns 1
7

I always use parseInt, but beware of leading zeroes that will force it into octal mode.

3 Comments

I think it's always a good idea to supply a radix to parseInt(value, radix) that way you don't have accidental octal mode conversions, etc.
Leading zeroes will force it into octal mode in ECMAScript 3. ECMAScript 5 will parse it to 0, even in non-strict mode. But this has been fixed and now leading zeroes are just ignored, so parseInt("070") would become 70.
You should be using a linter as well that will warn you to provide a radix value into parseInt().
6

It's a good idea to stay away from parseInt and use Number and Math.round unless you need hex or octal. Both can use strings. Why stay away from it?

parseInt(0.001, 10)
0

parseInt(-0.0000000001, 10)
-1

parseInt(0.0000000001, 10)
1

parseInt(4000000000000000000000, 10)
4

It completely butchers really large or really small numbers. Oddly enough it works normally if these inputs are a string.

parseInt("-0.0000000001", 10)
0

parseInt("0.0000000001", 10)
0

parseInt("4000000000000000000000", 10)
4e+21

Instead of risking hard to find bugs with this and the other gotchas people mentioned, I would just avoid parseInt unless you need to parse something other than base 10. Number, Math.round, Math.floor, and .toFixed(0) can all do the same things parseInt can be used for without having these types of bugs.

If you really want or need to use parseInt for some of it's other qualities, never use it to convert floats to ints.

4 Comments

Wow, this is really useful! Bugs from parseInt could be hard to find indeed. Your answer deserves many more upvotes!
That’s because parseInt expects strings. Any non-string is first coerced to a string. Since 4000000000000000000000 is not a safe integer, its string representation is 4e+21, and parseInt’s left-to-right parsing stops before the non-digit e. Using parseInt with numeric arguments or to round a number is a misuse.
The MDN reference for parseInt should be checked by anyone who thinks this answer deserves an upvote. The parseInt function does not accept a number. It's for parsing strings. If you use JavaScript, it will coerce the number into a string before the function receives the argument (which is what causes the rounding) and if you use TypeScript it won't even compile because it's wrong. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Yeah, I said that. Number and Math.round can both use strings as well.
0

parseInt converts to a integer number, that is, it strips decimals. Number does not convert to integer.

2 Comments

Just for fun it seems that e.g. Number("10.0") does return 10, but Number("10.1") returns 10.1. So, that's a fun special case to watch out for.
@CharlesWood That's not a Number() gotcha though. There is no concept of 10.0 in JS.
-1

Another way to get the result is to use the ~ operator

For most circumstances

~~someThing === parseInt(something)

but ~~ will return zero for strings that parseInt will accept with trailing other characters or with the number base spec (eg hex) and will also return zero when parseInt returns NaN. Another difference is that ~~ if given a bigint returns a bigint to which you can add another bigint whereas parseInt returns an ordinary floating point number (yes really - it gives exactly the same value as parseFloat) if the bigint is large

However for most circumstances ~~ is 30% faster than parseInt. It is only slower by 10% when something is a floating point represented as a string.

So if the more restricted scope of ~~ fits your need then save the computer time and give yourself less to type

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.