I've been following a course in Treehouse about JavaScript. I'm currently on the parseInt method. In one of their example, this code was shown:
var j = parseInt("012");
saving it and running in Chrome's console resulted to 10 in their example (which is understandable as 012 is 10 in octal), but in my own browser, it resulted to 12. Is it correct or am I doing something wrong?
It's not strange - the behavior is actually implementation dependent.
It could parse as octal 012 or decimal 12.
It's always best to specify the radix parameter when using parseInt(), for example parseInt('012', 10).
The difference comes from the type of your variable.
A Number 012 is considered octal, so parseInt(012) is 10.
A String "012" is nothing until parsed. By default parseInt will consider a string as a decimal value, hence "012" will be parsed as 12.
parseInt uses the decimal base by default, but you can force it to the octal base if you like:
parseInt("012", 8) === parseInt(12, 8) === 10
parseInt( 012 , 8) === parseInt(8, 10) === 8
Related
How do parseInt() and Number() behave differently when converting strings to numbers?
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
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.
One minor difference is what they convert of undefined or null,
Number() Or Number(null) Or Number('') // returns 0
while
parseInt() Or parseInt(null) // returns NaN
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
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.
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)
http://jsben.ch/#/zGJHM
http://phrogz.net/js/string_to_number.html
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
I always use parseInt, but beware of leading zeroes that will force it into octal mode.
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.
parseInt converts to a integer number, that is, it strips decimals. Number does not convert to integer.
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
I'm taking a numerical input as an argument and was just trying to account for leading zeroes. But it seems javascript converts the number into octal before I can do anything to the number. The only way to work around it so far is if I pass the number as a string initially but I was hoping there'd be another way to convert it after it is passed? So far tried (using 017 which alerted me to the octal behaviour):
017.toString(10) // 15
parseInt(017,10) // 15
017 + "" //15
new Number(017) //15
new Number('017') //17
parseInt('017', 10) // 17
So given
function(numb) {
if (typeof numb === number) {
// remove leading zeroes and convert to decimal
}
else {
// use parseInt
}
}
'use strict' also doesn't seem to solve this as some older posts have suggested. Any ideas?
If you take "numerical input", you should always definitely guaranteed have a string. There's no input method in this context that I know that returns a Number. Since you receive a string, parseInt(.., 10) will always be sufficient. 017 is only interpreted as octal if written literally as such in source code (or when missing the radix parameter to parseInt).
If for whatever bizarre reason you do end up with a decimal interpreted as octal and you want to reverse-convert the value back to a decimal, it's pretty simple: express the value in octal and re-interpret that as decimal:
var oct = 017; // 15
parseInt(oct.toString(8), 10) // 17
Though because you probably won't know whether the input was or wasn't interpreted as octal originally, this isn't something you should have to do ever.
JavaScript interprets all numbers beginning with a 0, and containing all octal numerals as octals - eg 017 would be an octal but 019 wouldn't be. If you want your number as a decimal then either
1. Omit the leading 0.
2. Carry on using parseInt().
The reason being is that JavaScript uses a few implicit conversions and it picks the most likely case based on the number. It was decided in JavaScript that a leading 0 was the signal that a number is an octal. If you need that leading 0 then you have to accept that rule and use parseInt().
Source
If you type numbers by hand to script then not use leading zeros (which implicity treat number as octal if it is valid octal - if not then treat it as decimal). If you have number as string then just use + operator to cast to (decimal) number.
console.log(+"017")
if (021 < 019) console.log('Paradox');
The strict mode will not allow to use zero prefix
'use strict'
if (021 < 019) console.log('Paradox');
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Workarounds for JavaScript parseInt octal bug
I would think it has something to do with octal parsing, since it only happens on 8 or 9. There was also the thought that this was a Chrome bug, but it replicates in Firefox as well.
Is this intentional behavior? If so, why?
The solution here is simple. NEVER call parseInt() without specifying the desired radix. When you don't pass that second parameter, parseInt() tries to guess what the radix is based on the format of the number. When it guesses, it often gets it wrong.
Specify the radix like this and you will get the desired result:
parseInt("08", 10) == 8;
As to what rules it uses for guessing, you can refer to the MDN doc page for parseInt().
If radix is undefined or 0, JavaScript assumes the following:
If the input string begins with "0x" or "0X", radix is 16
(hexadecimal).
If the input string begins with "0", radix is eight
(octal). This feature is non-standard, and some implementations
deliberately do not support it (instead using the radix 10). For this
reason always specify a radix when using parseInt.
If the input string
begins with any other value, the radix is 10 (decimal). If the first
character cannot be converted to a number, parseInt returns NaN.
So, according to these rules, parseInt() will guess that "08" is octal, but then it encounters a digit that isn't allowed in octal so it returns 0.
When you pass a number to parseInt(), it has nothing to do because the value is already a number so it doesn't try to change it.
"Is this intentional behavior?"
Yes.
"If so, why?"
A leading 0 is the notation used for denoting an octal number as defined in the specification. The symbols 8 and 9 don't exist in octal numbering, so parseInt uses the first valid number it finds, which is 0.
If you do...
parseInt('123#xq$_.f(--_!2*')
...the result will be...
123
...because a valid number was found at the beginning of the string. Anything invalid beyond that is discarded.
You can fix this like that :
parseInt("080".replace(/^[0]+/g,""));
This question already has answers here:
Javascript parseInt() with leading zeros
(7 answers)
Closed 4 years ago.
Why is this behavior difference between parseInt() and parseFloat()?
I have a string that contains 08 in it.
When I write this code:
alert(hfrom[0]);
alert(parseInt(hfrom[0]));
alert(parseFloat(hfrom[0]));
The following output is generated:
08
0
8
Why does parseInt and parseFloat return two different results in this case?
parseInt() assumes the base of your number according to the first characters in the string. If it begins with 0x it assumes base 16 (hexadecimal). Otherwise, if it begins with 0 it assumes base 8 (octal). Otherwise it assumes base 10.
You can specify the base as a second argument:
alert(parseInt(hfrom[0], 10)); // 8
From MDN (linked above):
If radix is undefined or 0, JavaScript assumes the following:
If the input string begins with "0x" or "0X", radix is 16
(hexadecimal). If the input string begins with "0", radix is eight
(octal). This feature is non-standard, and some implementations
deliberately do not support it (instead using the radix 10). For this
reason always specify a radix when using parseInt. If the input string
begins with any other value, the radix is 10 (decimal).
you should always include the radix param with parseInt() ex parseInt('013', 10) otherwise it can convert it to a different numeric base:
parseInt('013') === 11
parseInt('013', 10) === 13
parseInt('0x13') === 19
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Workarounds for JavaScript parseInt octal bug
Surprisingly it returns 0. Why? and what's the (proper) solution to get correct results?
Use a radix:
var x = parseInt("08", 10);
Some JavaScript implementations add a third numeral system to the two defined by the standard (decimal, the default; and hex, prefixed with 0x): Octal, prefixed with 0. This is non-standard but acknowledged as common in the latest spec.
Since 8 is not a valid octal digit, parseInt stops there, returning the value 0.
By explicitly using a radix, you tell parseInt not to try to figure out what numeral system is being used but instead to use the one you specify. Your instinct when typing parseInt should always be to specify the radix; not doing so leaves you open to oddities.
"08" mean 8 based number. You should specify second argument.
parseInt("08", 10)
#T.J. gave a great explanation for the behaviour you see. Another way to parse a number string is to use unary +:
var num = +"08";
From http://www.bennadel.com/blog/2012-Exploring-Javascript-s-parseInt-And-parseFloat-Functions.htm:
Strings that start with "0" are assumed to be base8 (octal).
From MDC - parseInt:
If the input string begins with "0", radix is eight (octal). This feature is non-standard, and some implementations deliberately do not support it (instead using the radix 10). For this reason always specify a radix when using parseInt.
And the example:
parseInt("08"); // 0, '8' is not an octal digit.
That is, since no radix was passed in and the string begins with 0 octal is assumed. Since 8 is not an octal digit it cannot be parsed.
Solution? Always provide a radix parameter:
parseInt("08", 10);
If you run it through jslint, it'll squawk at you for not including the radix parameter. Yes, the radix is optional, but probably should be included every time. A number starting with 0 is assumed to be octal unless otherwise specified.
var foo = parseInt("08", 10);
Number prefixed with "0" is octal number. 8 is invalid octal number. so the result is 0