9
votes

Generally speaking, bit shifting (>> , <<) allows us to divide / multiply by ^2

Example :

      9 (base 10): 00000000000000000000000000001001 (base 2)
                   --------------------------------
 9 >> 2 (base 10): 00000000000000000000000000000010 (base 2) = 2 (base 10)

For negative numbers :

Likewise, -9 >> 2 yields -3, because the sign is preserved:

     -9 (base 10): 11111111111111111111111111110111 (base 2)
                   --------------------------------
-9 >> 2 (base 10): 11111111111111111111111111111101 (base 2) = -3 (base 10)

But looking at >>> which acts the same for positive numbers, but behaves differently for negative numbers :

mdn

Zero bits are shifted in from the left

I can't find any reason / usage for shifting 0 from the left ( which makes the whole number positive) from the left :

       -9 (base 10): 11111111111111111111111111110111 (base 2)
                     --------------------------------
 -9 >>> 2 (base 10): 00111111111111111111111111111101 (base 2) = 1073741821 (base 10)

Question :

In what scenarios should I use >>> ? I don't understand why should I ever want to pad zeros from the left and mess my negative number.

2
Read logical right shift, the >>> operator, >> preserves sign but >>> notGrijesh Chauhan
@GrijeshChauhan it's really helpful but it only explains how it works which I already know that. but in what scenarios I should use it ? I dont see any math operation with shifting those bits to the right and add left padding zeros. I mean , If I told you to divide a number by using bitwise operations - you would choose >> but when would you choose >>> ?Royi Namir
ok I read your question again. Somewhere I read that unsigned shift are frequently uses in graphics programming. I don't know how. so +.Grijesh Chauhan
Read: Read usage of >>> sometime we use in programming to for example I used here in my answerGrijesh Chauhan
@RoyiNamir it depends on how you read(interpret) 11111111111111111111111111110111. I may want to use as unsigned int 0xfffffff7 and do the right shift to divide it.L.B

2 Answers

5
votes

Let's say you were programming something to mimic a piece of hardware, specifically a shift register.

To make things easier I'll use 8 bits instead of 32 bits as in your question.

We can add 128 every time we want to feed a high bit into this shift-register, since it will make the leftmost bit 1.

// Assume n is initialised to 0, so n = 00000000 in binary
n += 128;                    // now n = 10000000 in binary

If we shift using >>> every time you want to simulate a clock cycle, then after 8 "clock cycles" we will have that 1 at the rightmost bit. If we read that rightmost bit out then we will get a delayed version of what was fed into the leftmost bit 8 cycles ago.


This is only one example where the bits are not interpreted as a number, and I am sure there are many more. I think you'll find a few more uses elsewhere, especially in software meant to mimic hardware circuits/building blocks.

6
votes

A simple and often use case is to convert a variable to 32-bit unsigned integer(UInt32). When you do variable >>> 0, the variable will stay the same if it is already a UInt32 and will be 0 if it is not. e.g.

enter image description here

using example:

function convert( arrayLikeVariable){
   // we dont know for sure if length is UInt32
   // e.g. arrayLikeVariable.length = "zavarakatranemia"
   // so we do >>> 0
   var len = arrayLikeVariable >>> 0 
   // Now len is UInt32 for sure. 
   [..]
   // code using the len
}

If you want a complete example see the Polyfill here:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf

if (!Array.prototype.indexOf)  Array.prototype.indexOf = (function(Object, max, min){
  "use strict";
  return function indexOf(member, fromIndex) {
    if(this===null||this===undefined)throw TypeError("Array.prototype.indexOf called on null or undefined");

    var that = Object(this), Len = that.length >>> 0, i = min(fromIndex | 0, Len);
    if (i < 0) i = max(0, Len+i); else if (i >= Len) return -1;

    if(member===void 0){ for(; i !== Len; ++i) if(that[i]===void 0 && i in that) return i; // undefined
    }else if(member !== member){   for(; i !== Len; ++i) if(that[i] !== that[i]) return i; // NaN
    }else                           for(; i !== Len; ++i) if(that[i] === member) return i; // all else

    return -1; // if the value was not found, then return -1
  };
})(Object, Math.max, Math.min);