Sign in to follow this  
Followers 0
Joni_78

C++ >>= Bitwise right shift assignment

18 posts in this topic

I'm having hard time understanding what this does, could someone explain this?

 

X = 50

Y = 210

 

X >>= (Y / 210);

Share this post


Link to post
Share on other sites

I'm having hard time understanding what this does, could someone explain this?

 

X = 50

Y = 210

 

X >>= (Y / 210);

 

That assignment divides X by 2.

 

Y / 210 = 1

 

shifting by 1 bit to the right divides by 2 so X = 50 / 2 = 25

 

If you want to find out why that happens you need to know how numbers are represented in binary first. You can find an explanation of the shift operations here.

Share this post


Link to post
Share on other sites

(base 10) 50 = (binary) 00110010. So shifting 1 bit right results in (binary) 000011001 = (base 10) 25

It's a common operator to use since it reduces code size and increases execution speed since the compiler doesn't have to load floating point and math libraries.

Must be careful though if you need the fractional part of the number for something.

 

Also, shifting 2 bits right = divide by 4, 3 bits, divide by 8, and conversely, shifting 1 bit left would be a multiply by 2, 2 bits = * 4, 3 bits = * 8, et cetera.

Share this post


Link to post
Share on other sites

Thanks. I was wondering if I could make the operator to multiply resulted 25 by 0.0011 and then return resulted 0.0275 as X making the last line on the code below obsolite?

X = 50
Y = 210

X >>= (Y / 210);
S = X * 0.0011;

?

Share this post


Link to post
Share on other sites

Thanks. I was wondering if I could make the operator to multiply resulted 25 by 0.0011 and then return resulted 0.0275 as X making the last line on the code below obsolite?

 

Only if X is a float/double, but then the previous shifting could not work properly.

Share this post


Link to post
Share on other sites

It's a common operator to use since it reduces code size and increases execution speed since the compiler doesn't have to load floating point and math libraries.

That's kinda misleading. Integer division is integer division. It does not cause the compiler to emit floating point instructions. And integer vs floating point math has nothing to do with whether external libraries are linked into the executable. Integer and floating point math is translated pretty much 1:1 to CPU instructions, there's no need for libraries there.

 

Furthermore, any compiler worth its salt is able to replace integer divisions with powers of 2 with the corresponding bit shifts automatically. Note that it might not necessarily do it because depending on CPU architectures, a bit shift is not necessarily faster than integer division.

 

See http://stackoverflow.com/a/6359099/154766.

2 people like this

Share this post


Link to post
Share on other sites

Or, since you're doing * 0.0011, multiply everything by 10000 so you lose the decimal point and don't require floats, and format the output accordingly.

Share this post


Link to post
Share on other sites

That's kinda misleading. Integer division is integer division. It does not cause the compiler to emit floating point instructions. And integer vs floating point math has nothing to do with whether external libraries are linked into the executable. Integer and floating point math is translated pretty much 1:1 to CPU instructions, there's no need for libraries there.

Furthermore, any compiler worth its salt is able to replace integer divisions with powers of 2 with the corresponding bit shifts automatically. Note that it might not necessarily do it because depending on CPU architectures, a bit shift is not necessarily faster than integer division.

See http://stackoverflow.com/a/6359099/154766.

Yes, I made a blanket statement which may not have been applicable to all situations.

 

Architectures which natively support division won't suffer from this as the compiler should use what hardware is available.

Share this post


Link to post
Share on other sites

Good point about architectures that don't have hardware division. I tend to forget just how much ARM sucks.

Share this post


Link to post
Share on other sites

Good point about architectures that don't have hardware division. I tend to forget just how much ARM sucks.

 

I can't speak for you, but when I learned the ARM ISA it included the SDIV and UDIV instructions. Below are quotes from the ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition.

 

A8.6.155 SDIV

Signed Divide divides a 32-bit signed integer register value by a 32-bit signed integer register value, and writes the result to the destination register. The condition code flags are not affected.

 

A8.6.237 UDIV

Unsigned Divide divides a 32-bit unsigned integer register value by a 32-bit unsigned integer register value, and writes the result to the destination register. The condition code flags are not affected.

Share this post


Link to post
Share on other sites

I can't speak for you, but when I learned the ARM ISA it included the SDIV and UDIV instructions. Below are quotes from the ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition.

Yes but from what I've read most embedded devices like smartphones don't use these instructions sets yet. See (http://wanderingcoder.net/2010/07/19/ought-arm/):

 

?But!? you may say, having finally returned victorious from the ARM manual ?You?re wrong! There is an ARM division instruction, even two! Here, sdiv and udiv!? Sorry to rain on your parade, but these instructions are only available in the ARMv7-R and ARMv7-M profiles (real-time and embedded, respectively ? think motor microcontrollers and wristwatches), not in ARMv7-A which is the profile that the iOS devices that have ARMv7 do support. Sorry!

 

Share this post


Link to post
Share on other sites

Asik, you caught me. Most of the ARM development I do is embedded (where I have to either write assembly or write my C code to take advantage of the hardware). Therefore I work primarily with ARMv7-M and sometimes ARMv7-R series processors. I know that ARMv7-A is much more commonly used in smartphones and non-embedded devices (like my Samsung Chromebook), but since I have never had to worry about writing assembly for them, I made the (apparently false) assumption that they used a superset of the ARMv7-M ISA. Although the post you linked to reads very much like a rant, it does have a lot of good information. Thanks for the link!

Share this post


Link to post
Share on other sites

I read somewhere bitwise shift are useful for some math operation like:

R = (X * Y) MOD M

where X, Y & M values are still in max bit-ness the CPU registers can handle, hence also the R;

but the (X*Y) results were definitively larger than the CPU registers limit.

Share this post


Link to post
Share on other sites

My favorite trick (Which isn't needed at all, but the logic behind it is useful) is this
 
A = B * (1 / C)
 
So instead of dividing B by C, you divide 1 by C to get the reciprocal, then multiply B by that. Divisions are often much sower in hardware than multiplications, so this can provide a nice speed up (Which is why compilers now do it automatically, hence why it's not needed at all)

Share this post


Link to post
Share on other sites

I've been trying to find a simple way to do this but haven't found anything. Anyone have any ideas?

 

X is random int between 1-99.

            if (X >= 99)
            {
                Z = Z * 0.198;
            }
            else if (X >= 98)
            {
                Z = Z * 0.197;
            }
            
            ...

            else if (X >= 3)
            {
                Z = Z * 0.102;
            }
 
           else if (X >= 2)
            {
                Z = Z * 0.101;
            }
            else
            {
                Z = Z * 0.1;
            }

Bitwise right shift assignment would work if only I could do something like this with it:

 

>>= (Y / 210) * 0.1;

Share this post


Link to post
Share on other sites

Can't you replace those dozens of if-elses with:

Z *= 0.1 + ((X - 1) / 100.0)

? I mean clearly that's the mathematical formula you're trying to hardcode for a specific range.

 
Not sure what X >>= (Y / 210) * 0.1 is supposed to be, the right-hand side expression is a double so you can't right-shift by that, and what is Y?

Share this post


Link to post
Share on other sites

 

Can't you replace those dozens of if-elses with:

Z *= 0.1 + ((X - 1) / 100.0)

? I mean clearly that's the mathematical formula you're trying to hardcode for a specific range.

 
Not sure what X >>= (Y / 210) * 0.1 is supposed to be, the right-hand side expression is a double so you can't right-shift by that, and what is Y?

 

 

Forget that, I was thinking about that for so long I didn't know what I was thinking anymore.

 

I would need to do some calculations based on what year it is. For example I have years 1990-2013, I would have to check what year it is and then multiply X by 0.1-0.23. I haven't found any other way than if else, I wonder if anyone have any simpler ideas to avoid long if else statement.

 

int year = 1990...2013

Int64 X = 20

Share this post


Link to post
Share on other sites

This is just a math problem. You need to find the relationship between the year and the factor. Work this out on paper, not in code.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0

  • Recently Browsing   0 members

    No registered users viewing this page.