-1

How Bitwise operator | works is explained in the doc here and video here. However, the purpose and meaning of | seems difficult to grasp just by reading simple examples provided in the links.

I was reading the source code of d3.shuffle, here is a line using |:

i = Math.random() * m-- | 0;

based on the source code, this line of code seems intend to assign a random index between 0 and m to i.

My question is :

  1. If the intention of this line of code is to create a random index between 0 and m, then how exactly | help to achieve it?

  2. In other words, how to understand the practical use and meaning of using | here, as at this moment I understand no why, nor I can use | in any other cases.

  3. to rephrase the second part: is there a sort of logic to help understand the three lines of codes altogether? or should we use the sense of rounding to understand these three lines below? If so, how? If not, what do the other two lines of codes mean?

    i = Math.random() * m-- | 0;

    i = Math.random() * m-- | 1;

    i = Math.random() * m-- | 2;

Thanks!

Daniel
  • 1,428
  • 3
  • 16
  • 35
  • 1
    It truncates a number to a 32 bits integer. – zerkms Jul 02 '16 at 11:06
  • Thanks @zerkms, I saw it in the doc, but it does not help me understand its practical meaning in the work, not even explain anything in this case above. – Daniel Jul 02 '16 at 11:10
  • Ok, so in that particular case seems like they use it just as a way to round a number. (that's another reason why boring code is better than a tricky one). – zerkms Jul 02 '16 at 11:13
  • Thanks @zerkms, it is helpful. – Daniel Jul 02 '16 at 13:20

2 Answers2

3

The logical OR will truncate a float to a 32-bit integer. See for instance this answer which suggests that method for truncating floats to integers.

How it works

The | implicitly coerces its operands to integer, because it is an integer-bitwise operator: it needs to operate on 32-bit integers.

Besides this coercion, a logical OR with 0 is a no-operation: no bits are set that are not already set in the other argument.

Other values than 0 would have an effect:

x | 1

This sets the least significant bit of x to 1, so the result is always odd. Some examples:

4 | 1 === 5
5 | 1 === 5
6 | 1 === 7 
7.123 | 1 === 7

Another example:

x | 2

This sets the one-but-least significant bit to 1. The value of that bit is 2, so this means the result will be either x itself, or x+2:

4 | 2 === 6
5 | 2 === 7
6 | 2 === 6
7 | 2 === 7
8 | 2 === 10

Look at these numbers in binary format to get a more clear view on what happens:

left argument:  00000100  (=4)
right argument: 00000010  (=2)
outcome of |:   00000110  (=6)

The outcome will have a bit set if, and only when, the corresponding bit is set in at least one of the arguments.

With this you can see that x | 0 does not alter x, except for the coercion to integer. So this operator is used not for its main purpose (bit-setting), but for its side-effect (coercion).

Effects on large numbers

Numbers outside of the 232 range (positive or negative) will be mapped into that range, resulting in potentially unexpected outcomes.

Community
  • 1
  • 1
trincot
  • 317,000
  • 35
  • 244
  • 286
  • Thanks for the update. It seems that there is no unifying logic for understanding the three lines of code in my question. Each turns out to perform for different things. – Daniel Jul 03 '16 at 00:20
2

In that case it is just a way to truncate a floating point number to an integer.

So you can read it as

i = Math.floor(Math.random() * m--);

They may have used an operator because:

  1. It perhaps is faster (needs an evidence)
  2. It's just the author's preference to round
zerkms
  • 249,484
  • 69
  • 436
  • 539
  • Thanks @zerkms for this great answer. I have edited the second (2, 3 bullet points) part of my question, could you have a look? – Daniel Jul 02 '16 at 13:33