4

I was looking at this question about how to efficiently check if a value is an integer. One answer recommended using n === (n|0) for some quick rounding via the | operator. On a whim, I decided to test it with Number.MAX_VALUE. Despite the fact that this should be an integer (I think?), the test came back false.

It also came back false for Number.MAX_SAFE_INTEGER, so I decided to test some other large numbers and found the following:

Number.MAX_VALUE | 0           --> 0
Number.MAX_SAFE_INTEGER | 0   --> -1
Number.MAX_SAFE_INTEGER/2 | 0 --> -1
Number.MAX_SAFE_INTEGER/8 | 0 --> -1
1234567890 | 0                --> 1234567890 

I'm not really sure what the | operator is doing internally, but it doesn't seem safe to do on MAX_SAFE_INTEGER. Why is that the case?

Community
  • 1
  • 1
ckersch
  • 7,507
  • 2
  • 37
  • 44

2 Answers2

3

The | operator in JavaScript converts its argument to a signed 32 bit integer, then does a bitwise or onto it. |0 or's zero, which leaves the value unchanged, so that has become a JavaScript convention for converting the value to a 32 bit integer (the same type as int in C on desktop processors, a fast datatype for processing as well as a convenient round).

I'm not sure if Number.MAX_SAFE_INTEGER is part of the standard; I just tried it in my IE and it came back undefined, but based on your description, it is probably giving you the biggest number that can fit in either 32 bits or a double (floating point): 2^32-1, about 4 billion in the case of the 32 bit and something much bigger for the float. But remember | gives you a /signed/ number, so there's really only 31 bits available. The other bit is used for negative numbers.

To store a negative number in binary (technically speaking, twos complement), you flip all the bits then add one to the result. One is stored 0001, so flip the bits and add one gives 1110+1 == 1111 (of course, longer value for 32 bit but same concept) which is the same representation as the maximum value when unsigned.

Adam D. Ruppe
  • 25,382
  • 4
  • 41
  • 60
  • 1
    `Number.MAX_SAFE_INTEGER` is a proposal for ECMAScript 6. It's defined as the biggest unsigned integer that fits in 53 bits, totally utilizing the mantissa of a double precision floating point (52 bits). The sign is stored separately, so `-Number.MAX_SAFE_INTEGER` is the min safe integer. All integers in the range `-(2^53-1) .. +(2^53-1)` have an unambiguous representation whereas e.g. `Math.pow(2, 53) === Math.pow(2, 53) + 1`. – Robert Oct 25 '14 at 19:02
1

While it is true that MAX_SAFE_INTEGER is an integer... it's an integer in double-precision float format, ie. 53 bits long.

Meanwhile, the bitwise operators work on 32-bit integers.

I think you can see where this is going ;)

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592