Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why :Math.floor(2e+21) != ~~(2e+21)

I am not an expert in bitwise operators, but i often see a pattern which is used by programmers of 256k demos at competitions. Instead of using Math.floor() function, double bitwise NOT operator is used ~~ ( maybe faster ? ).

Like this:

Math.floor(2.1); // 2
~~2.1 // 2

Search revealed that there are more patterns that used the same way:

2.1 | 0  // 2
2.1 >> 0 // 2

When playing with this in the dev console, i have noticed a behavior that i'm not sure i understand fully.

Math.floor(2e+21);  // 2e+21
~~2e+21;    // -1119879168
2e+21 | 0;  // -1119879168

What is happening under the hood ?

like image 747
Alexander Avatar asked Oct 27 '14 20:10

Alexander


People also ask

What is the difference between math floor and math round?

Math. round() - rounds to the nearest integer (if the fraction is 0.5 or greater - rounds up) Math. floor() - rounds down.

Is math Floor slow?

It suggests that Math. floor is the SLOWEST way to calculate floor in Javascript.

What is Math floor ()?

floor() The Math. floor() function returns the largest integer less than or equal to a given number.

How do you number a floor in JavaScript?

floor() function in JavaScript. The floor() function of the Math object accepts a floating point number and returns the largest integer less than or equal to the given number. If the given number itself is an integer this function returns the same.


1 Answers

As Felix King pointed out, the numbers are being converted to 32 bit signed integers. 2e9 is less than the maximum positive value of a signed int, so this works:

~~(2e9)  //2000000000

But when you go to 2e10, it can't use all the bits, so it just takes the lowest 32 bits and converts that to an int:

~~(2e10) //-1474836480

You can verify this by using another bitwise operator and confirming that it's grabbing the lowest 32 bits:

2e10 & 0xFFFFFFFF // also -1474836480
~~(2e10 & 0xFFFFFFFF) // also -1474836480

Math.floor is built to account for large numbers, so if accuracy over a big range is important then you should use it.

Also of note: The ~~ is doing truncation, which is the same as flooring for positive numbers only. It won't work for negatives:

Math.floor(-2.1) // -3
~~(-2.1) // -2
like image 92
Evan M Avatar answered Oct 21 '22 16:10

Evan M