So you have a decimal number that you want converted into an integer. You’ve come across parseInt
and think to yourself, “Boy, that sounds like the right function for me!”. So you try the following.
parseInt(1.655)
> 1
Great. It worked!
But later on…
parseInt(0.0000000060)
> 6
Whoops. Clearly something went wrong here.
So what happened? If you cast 0.000000006
as a Number
in your DevTools console, you’ll see the value 6e9
. This is a shorthand mathematical form used when there’s lots of consecutive 0s.
Let’s quickly go to the MDN spec to see what parseInt
actually does.
The parseInt() function parses a string argument and returns an integer of the specified radix (the base in mathematical numeral systems).
If the string argument is not a string, then it is converted to a string (using the ToString abstract operation). – MDN
Back to our problem, what has happened is that the number 0.000000006
was first converted to a string, which is "6e9"
, as per the spec.
It then tried to parse the string, but came across an e
character, which is not a number. Well, technically it is! It’s approximately 2.718, but let’s not get into logarithms! It bails out at e
, and returns what it has to that point. In this case, 6
.
If we now perform the same action using a string representation of the original number, we get the correct answer:
parseInt('0.000000006')
> 0
It’s clear that parseInt
is not super safe. It tries to be clever by coercing, but it fails in some circumstances. One solution is to put quotes around your numbers and use the function as it was primarily intended.
However, it’s probably not very memory efficient or speedy to use strings to get around this problem, particularly if you are dealing with lots of values.
You can use Math
functions to round or truncate numbers to form integers, such as Math.round
, Math.ceil
, Math.floor
and Math.trunc
.
My preferred solution is Math.trunc
because it simply truncates everything from the decimal point, and doesn’t apply any rounding logic.
Math.trunc(1.655)
> 1
Math.trunc(0.000000006)
> 0
You can implement the truncation logic very simply using Math.ceil
and Math.floor
in cases where you cannot run ES2015 functions.
function ToInteger(v) {
if (v > 0) {
return Math.floor(v);
}
return Math.ceil(v);
}
ToInteger(0.000000006)
> 0
A potentially faster method of converting a number to an integer is to use bitwise operators. Bitwise in JavaScript works by converting the operands of an operation to 32bit signed integer representation, and then flips or shifts bits where applicable.
We can use the OR operator as below.
1.655  0
> 1
1.655
gets converted to 0b00000001
when used in a bitwise operation. This is 1 in binary. That’s it. It’s done the truncation and returned the integer for us.
In order to coerce the JavaScript engine to do this, we had to provide two operands and a bitwise operator, but we didn’t want to make any changes to the left operand.
The OR operator yields a 1 for each bit column if either operand has a 1 in the corresponding column. By using 0 as the right operand, the return value in every column is the same.
00000001

00000000
> 00000001
The same behaviour can be achieved with the shift operator, >>
The drawback to this solution is that we can only use numbers in 32bit representation. Numbers in JavaScript are 64bit floating points, so we can represent much higher values if we wanted to.
If we attempt to convert 4000000000000000000000.1
to an integer with this method, we get an overflow.
4000000000000000000000.1  0
> 2055208960
Method 1 didn’t suffer from this. If you can guarantee not to have large values (+/ 2^32), use bitwise, otherwise I recommend using Math.trunc
, or perhaps Math.round
if you prefer to round up/down.