Search code examples
javascriptnumbersbitwise-operatorsarithmetic-expressions

Is any float number | 0 = a fixed number?


Suppose I wrote the codes like this following:

console.log((5/3)|0)

The result is 1.

However why? In my mind, |0 means +0. But why can it cancel off the fractional part?

Can anyone give me a full understanding of that by showing its inner binary digits and how can I get that result step by step?


Solution

  • Here, the operator | is bitwise OR, and involves analyzing the bits of that float the computer internally stores. This is because all floats are really expressed as 32 bits.

    The value 0 has all 32 bits equal to 0. A 1 or 0 bit OR 0 will still be 1, 0 respectively, so all 32 bits remain the same.

    Normally, all JS numbers are doubles (64-bit floating point numbers). Beware that before the bitwise OR is completed, the JS compiler will convert the floating-point operands into its signed int form temporarily, meaning that it could result in a different value, notably the truncating of the decimal part. After the bitwise operation is done, JS will convert it back to floating-point numbers.

    Here is an example of how a float value is truncated to a signed int after bitwise OR:

    var x = 100/3.0;
    console.log(x);   // outputs 33.333333333333336
    console.log(x|0); // outputs 33 (no decimal)
    

    How your bitwise operators work step-by-step

    There is a Mozilla documentation about the Javascript bitwise operators.

    "The operands of all bitwise operators are converted to signed 32-bit integers in two's complement format."

    Step by step, the bits are (let them be single-precision floats for brevity, JS decimals are doubles):

    • 100 / 3: 0 10000100 0000101 01010101 01010101
      • Exponent bit is 132, which is 5 unbiased, the mantissa bit is slightly greater than 1
    • 100 / 3 is casted to 32-bit int form before bitwise OR, yielding integer 33
    • 33 : 0000 0000 0000 0000 0000 0000 0010 0001
    • 0 : 0000 0000 0000 0000 0000 0000 0000 0000
    • 33 | 0 : 0000 0000 0000 0000 0000 0000 0010 0001 yielding integer 33 again.
    • After bitwise operation is completed, 33 is converted back to floating-point.