|
-
March 1st, 2010, 04:10 PM
#1
* 8 vs << 3
I'm just curious, how many programmers explicitly do bit shifting? I'm sure that the compiler will convert a multiplication / division by a factor of 2 into a bit shift, but I tend to do it explicitly anyway and some people complain to me that that's more difficult to follow when they end up reading my code.
-
March 1st, 2010, 04:32 PM
#2
Re: * 8 vs << 3
It depends on the context which method I prefer. If you are doing operations on bits - e.g. using them as flags or changing endianness - then I prefer bitwise operators. If you are multiplying with a constant that just happens to be 8 then I'd prefer to multiply with a const int that gives a more descriptive name to the magic number 8.
Cheers, D Drmmr
Please put [code][/code] tags around your code to preserve indentation and make it more readable.
As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky
-
March 1st, 2010, 04:41 PM
#3
Re: * 8 vs << 3
personally, if I want to say '*8' I write *8 and if I want to say "*2^3" I write "<<3"... seriously, given that it's not good practice using "magic" numbers (as suggested by D_Drmmr), I would end up with two cases: "* some_factor" or "<< some_exponent" , as you can see they mean different things: so the final choice boils down to ask myself if the concept I'm expressing fits more naturally as a factor or as a (base-2) exponent.
-
March 1st, 2010, 05:03 PM
#4
Re: * 8 vs << 3
The compiler (certainly VStudio anyway) generates the same code for both cases so there is no performance gain in shifting over multiplying.
I agree with both superbonzo and D_Drmmr. I try to pick the one which logically suits the context best.
-
March 7th, 2010, 10:44 PM
#5
Re: * 8 vs << 3
This is just basically echoing what others have said, but unless the context is in an embedded system, or you're explicitly doing bitwise operations, I would prioritize code clarity above all. In embedded system context, I would use the shifting explicitly only because I am not 100% confident I can trust the compiler to optimize as it should, so I'm not taking any chances since I want this code to be as open platform as possible. In the end, though, if we're talking a high-level system context it shouldn't matter for speed, even if for some strange reason the compiler *didn't* optimize, in which case, my coding standard is always to prefer clarity (here again though, bit shifting can actually provide better clarity depending on the context). So to be more concise: bit-shifting for the sake of bit-shifting I would not accept.
-
March 7th, 2010, 10:56 PM
#6
Re: * 8 vs << 3
When right-shifting, it's implementation-defined whether the shift is arithmetic or logical on signed integers. Most implementations make it arithmetic. (It's logical on unsigneds, of course.)
However, even with an arithmetic shift, I have heard that there's a difference between doing >> 3 or dividing by 8: One will always round down, while the other always rounds towards zero. Which could make a difference for negative numbers.
-
March 7th, 2010, 10:59 PM
#7
Re: * 8 vs << 3
<temporary hijack>
What's the difference between an arithmetic and logical shift?
</temporary hijack>
-
March 7th, 2010, 11:02 PM
#8
Re: * 8 vs << 3
Basically, whether or not right-shifting a negative number keeps it negative. The difference is whether the new bits on the left are filled with 0s or 1s when faced with an active sign bit (negative). If you know how 2s-complement representations work, it makes sense.
-
March 8th, 2010, 05:08 PM
#9
Re: * 8 vs << 3
 Originally Posted by Lindley
However, even with an arithmetic shift, I have heard that there's a difference between doing >> 3 or dividing by 8: One will always round down, while the other always rounds towards zero. Which could make a difference for negative numbers.
I'd never heard that before so I got curious and did some code to test this and yes it's true. The reason is the 2s-complement representation. Dividing an odd negative number by shifting will mean that the number is "truncated" the wrong way, instead of reducing the result by one it's added by one.
Code:
org , n, m, org>>n, org/m
127, 0, 1, 127(01111111), 127(01111111)
127, 1, 2, 63(00111111), 63(00111111)
127, 2, 4, 31(00011111), 31(00011111)
127, 3, 8, 15(00001111), 15(00001111)
127, 4, 16, 7(00000111), 7(00000111)
127, 5, 32, 3(00000011), 3(00000011)
127, 6, 64, 1(00000001), 1(00000001)
126, 0, 1, 126(01111110), 126(01111110)
126, 1, 2, 63(00111111), 63(00111111)
126, 2, 4, 31(00011111), 31(00011111)
126, 3, 8, 15(00001111), 15(00001111)
126, 4, 16, 7(00000111), 7(00000111)
126, 5, 32, 3(00000011), 3(00000011)
126, 6, 64, 1(00000001), 1(00000001)
125, 0, 1, 125(01111101), 125(01111101)
125, 1, 2, 62(00111110), 62(00111110)
125, 2, 4, 31(00011111), 31(00011111)
125, 3, 8, 15(00001111), 15(00001111)
125, 4, 16, 7(00000111), 7(00000111)
125, 5, 32, 3(00000011), 3(00000011)
125, 6, 64, 1(00000001), 1(00000001)
-121, 0, 1, -121(10000111), -121(10000111)
-121, 1, 2, -61(11000011), -60(11000100)
-121, 2, 4, -31(11100001), -30(11100010)
-121, 3, 8, -16(11110000), -15(11110001)
-121, 4, 16, -8(11111000), -7(11111001)
-121, 5, 32, -4(11111100), -3(11111101)
-121, 6, 64, -2(11111110), -1(11111111)
-125, 0, 1, -125(10000011), -125(10000011)
-125, 1, 2, -63(11000001), -62(11000010)
-125, 2, 4, -32(11100000), -31(11100001)
-125, 3, 8, -16(11110000), -15(11110001)
-125, 4, 16, -8(11111000), -7(11111001)
-125, 5, 32, -4(11111100), -3(11111101)
-125, 6, 64, -2(11111110), -1(11111111)
-126, 0, 1, -126(10000010), -126(10000010)
-126, 1, 2, -63(11000001), -63(11000001)
-126, 2, 4, -32(11100000), -31(11100001)
-126, 3, 8, -16(11110000), -15(11110001)
-126, 4, 16, -8(11111000), -7(11111001)
-126, 5, 32, -4(11111100), -3(11111101)
-126, 6, 64, -2(11111110), -1(11111111)
-127, 0, 1, -127(10000001), -127(10000001)
-127, 1, 2, -64(11000000), -63(11000001)
-127, 2, 4, -32(11100000), -31(11100001)
-127, 3, 8, -16(11110000), -15(11110001)
-127, 4, 16, -8(11111000), -7(11111001)
-127, 5, 32, -4(11111100), -3(11111101)
-127, 6, 64, -2(11111110), -1(11111111)
-128, 0, 1, -128(10000000), -128(10000000)
-128, 1, 2, -64(11000000), -64(11000000)
-128, 2, 4, -32(11100000), -32(11100000)
-128, 3, 8, -16(11110000), -16(11110000)
-128, 4, 16, -8(11111000), -8(11111000)
-128, 5, 32, -4(11111100), -4(11111100)
-128, 6, 64, -2(11111110), -2(11111110)
Guess the rule that say 'only use bit operators on unsigned data' wasn't invented just to annoy people...
-
March 8th, 2010, 05:25 PM
#10
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|