Tuesday, March 15, 2011

Shifty eyes

Right shift, left shift. These are not just keys on your keyboard. They are the names of mathematical operations that are enormously convenient and helpful in the world of binary math.


First I'll explain what they are, and then I'll explain why they're so helpful. A shift in either direction basically amounts to picking up a binary number, moving it a few places to either the right or left and then plopping it back down. Remember, those "places" in binary numbers are the "2s place," the "4s place," the "8s place," and so on. If you shift a number to the right and some digits get shifted right off the end, then so be it. Similarly, if you shift a number to the left, you have to invent new digits in the low places of that number. Shifting is often represented with these symbols: ">>" for right shift, and "<<" for left shift (see, it's like a double arrow pointing in the direction of the shift).


Here's an example of a right shift of a single-byte binary number:


0b1100 0101 >> 4 = 0b0000 1100


and here's an example of a left shift of a single-byte binary number:


0b0001 1010 << 3 = 0b1101 0000


Do you see how it's like we just picked up the original number and plopped it down in a new place? The right shifted number ended up 4 places to the right, and the left shifted number ended up 3 places to the left.


Here are another couple of examples using decimal that will give you a hint as to why shifting is so helpful in computers:


4563 >> 2 = 45

23 << 3 = 23000


You'll notice in those decimal examples that shifting right by 2 is the same as dividing by 100 (ignoring the resulting remainder or fractions, we're just talking about integers here). Also notice that shifting left by 3 is the same as multiplying by 1000. So now we're starting to see how this is a really nice tool for a computer to have.


Let's look at single-byte binary numbers again and do 2 more concrete examples:


0b1000 0001 >> 1 = 0b0100 0000 (129 shifted right by 1 = 64)

0b0000 0011 << 4 = 0b0011 0000 (3 shifted left by 4 = 48)


Using that exponent notation again from an earlier post, a right shift is like dividing by 2^x (where x is the amount shifted), and a left shift is like multiplying by 2^x (where x is again the amount shifted). When left shifting (multiplying) you need to be careful because you might shift some 1s clear off the end of the binary number, and the result won't really be the correct answer for multiplication. Also, we can only work in powers of two here. If you want to multiply or divide by 3, for example, you cannot do that with a single shift like you can when multiplying or dividing by 2 or 4 (which are powers of 2).


The great thing about the shift operation is that it's so fast. It's even faster and easier than addition to do a in a processor. In our program loop branching example we multiplied 7 by 8, and it took us 8 trips through that loop, adding 7 to a variable each time around. With shifting we can get that same result in a single operation, like this:


0b0000 0111 << 3 = 0b0011 1000 (shift left by 3 because 8=2^3)


And that's it for shifting. I don't have a plan for my next post, but I'll make another one soon anyway.

1 comment:

  1. I found this today and I thought it could be an idea for a future post: http://www.victusspiritus.com/2011/03/14/brushing-up-on-computer-science-part-1-big-o/

    I think there's probably a lot more than you need to cover before time complexity becomes accessible to a general audience, but it might give you some ideas.

    ReplyDelete