Converting a double to an int in Javascript without rounding

JavascriptCastingFloating PointInt

Javascript Problem Overview


In C# the following code returns 2:

double d = 2.9;
int i = (int)d;
Debug.WriteLine(i);

In Javascript, however, the only way of converting a "double" to an "int" that I'm aware of is by using Math.round/floor/toFixed etc. Is there a way of converting to an int in Javascript without rounding? I'm aware of the performance implications of Number() so I'd rather avoid converting it to a string if at all possible.

Javascript Solutions


Solution 1 - Javascript

Use parseInt().

var num = 2.9
console.log(parseInt(num, 10)); // 2

You can also use |.

var num = 2.9
console.log(num | 0); // 2

Solution 2 - Javascript

I find the "parseInt" suggestions to be pretty curious, because "parseInt" operates on strings by design. That's why its name has the word "parse" in it.

A trick that avoids a function call entirely is

var truncated = ~~number;

The double application of the "~" unary operator will leave you with a truncated version of a double-precision value. However, the value is limited to 32 bit precision, as with all the other JavaScript operations that implicitly involve considering numbers to be integers (like array indexing and the bitwise operators).

edit — In an update quite a while later, another alternative to the ~~ trick is to bitwise-OR the value with zero:

var truncated = number|0;

Solution 3 - Javascript

Similar to C# casting to (int) with just using standard lib:

Math.trunc(1.6) // 1
Math.trunc(-1.6) // -1

Solution 4 - Javascript

Just use parseInt() and be sure to include the radix so you get predictable results:

parseInt(d, 10);

Solution 5 - Javascript

There is no such thing as an int in Javascript. All Numbers are actually doubles behind the scenes* so you can't rely on the type system to issue a rounding order for you as you can in C or C#.

You don't need to worry about precision issues (since doubles correctly represent any integer up to 2^53) but you really are stuck with using Math.floor (or other equivalent tricks) if you want to round to the nearest integer.


*Most JS engines use native ints when they can but all in all JS numbers must still have double semantics.

Solution 6 - Javascript

A trick to truncate that avoids a function call entirely is

var number = 2.9
var truncated = number - number % 1;
console.log(truncated); // 2 

To round a floating-point number to the nearest integer, use the addition/subtraction trick. This works for numbers with absolute value < 2 ^ 51.

var number = 2.9
var rounded = number + 6755399441055744.0 - 6755399441055744.0;  // (2^52 + 2^51)
console.log(rounded); // 3 

Note:

Halfway values are rounded to the nearest even using "round half to even" as the tie-breaking rule. Thus, for example, +23.5 becomes +24, as does +24.5. This variant of the round-to-nearest mode is also called bankers' rounding.

The magic number 6755399441055744.0 is explained in the stackoverflow post "A fast method to round a double to a 32-bit int explained".

// Round to whole integers using arithmetic operators
let trunc = (v) => v - v % 1;
let ceil  = (v) => trunc(v % 1 > 0 ? v + 1 : v);
let floor = (v) => trunc(v % 1 < 0 ? v - 1 : v);
let round = (v) => trunc(v < 0 ? v - 0.5 : v + 0.5);

let roundHalfEven = (v) => v + 6755399441055744.0 - 6755399441055744.0; // (2^52 + 2^51)

console.log("number  floor   ceil  round  trunc");
var array = [1.5, 1.4, 1.0, -1.0, -1.4, -1.5];
array.forEach(x => {
    let f = x => (x).toString().padStart(6," ");
    console.log(`${f(x)} ${f(floor(x))} ${f(ceil(x))} ${f(round(x))} ${f(trunc(x))}`);  
});

Solution 7 - Javascript

As @Quentin and @Pointy pointed out in their comments, it's not a good idea to use parseInt() because it is designed to convert a string to an integer. When you pass a decimal number to it, it first converts the number to a string, then casts it to an integer. I suggest you use Math.trunc(), Math.floor(), ~~num, ~~v , num | 0, num << 0, or num >> 0 depending on your needs. This performance test demonstrates the difference in parseInt() and Math.floor() performance. Also, this post explains the difference between the proposed methods.

Solution 8 - Javascript

What about this:

if (stringToSearch.IndexOfAny( ".,;:?!".ToCharArray() ) == -1) { ... }

Solution 9 - Javascript

I think that the easiest solution is using the bitwise not operator twice:

const myDouble = -66.7;
console.log(myDouble); //-66.7
const myInt = ~~myDouble;
console.log(myInt); //-66
const myInt = ~~-myDouble;
console.log(myInt); //66

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRory HarveyView Question on Stackoverflow
Solution 1 - JavascriptkubetzView Answer on Stackoverflow
Solution 2 - JavascriptPointyView Answer on Stackoverflow
Solution 3 - JavascriptRolandView Answer on Stackoverflow
Solution 4 - JavascriptJustin NiessnerView Answer on Stackoverflow
Solution 5 - JavascripthugomgView Answer on Stackoverflow
Solution 6 - JavascriptAmr AliView Answer on Stackoverflow
Solution 7 - Javascript1manView Answer on Stackoverflow
Solution 8 - JavascriptBelugaView Answer on Stackoverflow
Solution 9 - JavascriptDulorenView Answer on Stackoverflow