0

In JavaScript there is no special type for integer values. Actually, all numbers has a Number type which is Double Precision Floating Point Number (IEEE 754) i.e. binary64.

One of the problems with numeric operations in JavaScript is that there is no integer division operator or function defined in the standard.

UPDATE: actually, there is a Math.trunc() function, but it works ~2-5 times slower than binary solution and it's not supported in Internet Explorer.

Some binary operators could be used to achieve the desired result, e.g.:

  • (10 / 4) >> 0
  • ~~(10 / 4)
  • (10 / 4) | 0

All operations above produces number 2 and according to my benchmarks, have a similar performance on my x64 machine (Node.js v7.2.1).

Could you please explain how exactly are those binary operations work for this exact purpose? Is there a preferred one?

Slava Fomin II
  • 26,865
  • 29
  • 124
  • 202

4 Answers4

2

Those operations are not straightforward way of converting float to int. These are binary operations and it works on integer. In this process there is automatic conversion. So this is abusing but somewhat faster way of converting floats to int. However as these operations are very often used in javascript, there is not much harm in using them. However, Math.floor() or Math.truncate () can also be used for better readability.

Prabir Ghosh
  • 430
  • 3
  • 7
  • Thank you for a `Math.trunc()` suggestion. The weird thing is that it wasn't mentioned anywhere I looked for an integer division. – Slava Fomin II Jan 13 '17 at 12:56
1

Bit-wise operators only work on integers in Javascript so performing any of them truncates a value to an integer.

(10 / 4) >> 0

Performs a division (10 / 4) to obtain the value 2.5, bit shifts (>>) only work on integer values and so by performing a bit-shift on 2.5, the value is truncated to 2.

The same is the case for

(10 / 4) | 0

Except rather than a bit-shift, the operation is a bit-wise or.

~~(10 / 4)

Performs a double bit-wise negation, the first truncating and negating making 2.5 turn into -3, and then another to convert it back to the correct sign, 2.

You can learn more by reading about bit-wise operators here: http://www.w3schools.com/jsref/jsref_operators.asp

Nick is tired
  • 6,860
  • 20
  • 39
  • 51
1

First of all, you are convering Numbers to signed 32 bit integers, which means, you lose some digits, compared to 64 bit floating point representation.

The calculation of your numbers is just giving a floating point value of 2.5 and the operands are first converted to a signed 32 bit integer number, then the bitwise calculation takes place. The operand is necessary, because you need it for the initial conversation.

Example for 2 >> 0 Sign-propagating right shift >>

     2 (base 10): 00000000000000000000000000000010 (base 2)
                  --------------------------------
2 >> 0 (base 10): 00000000000000000000000000000010 (base 2) = 2 (base 10)

Example for ~~2 Bitwise NOT ~

     2 (base 10): 00000000000000000000000000000010 (base 2)
                  --------------------------------
    ~2 (base 10): 11111111111111111111111111111101 (base 2) = -3 (base 10)
                  --------------------------------
   ~~2 (base 10): 00000000000000000000000000000010 (base 2) =  2 (base 10)

Example for 2 | 0 Bitwise OR |

     2 (base 10): 00000000000000000000000000000010 (base 2)
     0 (base 10): 00000000000000000000000000000000 (base 2)
                  --------------------------------
 2 | 0 (base 10): 00000000000000000000000000000010 (base 2) = 2 (base 10)

Beside the possibillity to convert a number to an integer representation, you could use plain Math.floor for the same purpose and it makes the code not look cryptic.

Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • Thank you for a comprehensive explanation. It makes sense. However, `Math.floor()` will not work on negative numbers as expected. – Slava Fomin II Jan 13 '17 at 12:53
  • yes, because of *"The `Math.floor()` function returns the largest integer less than or equal to a given number."*. – Nina Scholz Jan 13 '17 at 12:55
0

These aren't really binary tricks - it's just that all three of the operators in use (~, >> and |) are defined as only working on the first 32 (signed) bits of a Number.

Any (double precision) operand that isn't an integer will be truncated so that it is, and any bits beyond 1 << 32 are discarded before the operation is evaluated.

Alnitak
  • 334,560
  • 70
  • 407
  • 495