Jump to content



Photo

C++ >>= Bitwise right shift assignment


  • Please log in to reply
17 replies to this topic

#1 Joni_78

Joni_78

    Neowinian Senior

  • Joined: 19-April 04
  • Location: Finland
  • OS: Windows 8 Pro with Media Center, OS X Mavericks 10.9.4
  • Phone: Nokia Lumia 920

Posted 02 October 2013 - 05:54

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

 

X = 50

Y = 210

 

X >>= (Y / 210);




#2 francescob

francescob

    Neowinian Senior

  • Tech Issues Solved: 1
  • Joined: 04-November 08

Posted 02 October 2013 - 06:03

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.



#3 abecedarian paradoxious

abecedarian paradoxious

    cell tech

  • Tech Issues Solved: 1
  • Joined: 04-November 07

Posted 02 October 2013 - 06:28

(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.



#4 OP Joni_78

Joni_78

    Neowinian Senior

  • Joined: 19-April 04
  • Location: Finland
  • OS: Windows 8 Pro with Media Center, OS X Mavericks 10.9.4
  • Phone: Nokia Lumia 920

Posted 02 October 2013 - 07:12

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;





#5 francescob

francescob

    Neowinian Senior

  • Tech Issues Solved: 1
  • Joined: 04-November 08

Posted 02 October 2013 - 08:13

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.



#6 Andre S.

Andre S.

    Asik

  • Tech Issues Solved: 14
  • Joined: 26-October 05

Posted 02 October 2013 - 15:55

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.../6359099/154766.



#7 abecedarian paradoxious

abecedarian paradoxious

    cell tech

  • Tech Issues Solved: 1
  • Joined: 04-November 07

Posted 02 October 2013 - 15:57

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.



#8 abecedarian paradoxious

abecedarian paradoxious

    cell tech

  • Tech Issues Solved: 1
  • Joined: 04-November 07

Posted 02 October 2013 - 15:58

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.../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.



#9 Andre S.

Andre S.

    Asik

  • Tech Issues Solved: 14
  • Joined: 26-October 05

Posted 02 October 2013 - 17:07

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



#10 +Karl L.

Karl L.

    xorangekiller

  • Tech Issues Solved: 15
  • Joined: 24-January 09
  • Location: Virginia, USA
  • OS: Debian Testing

Posted 02 October 2013 - 22:26

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.



#11 Andre S.

Andre S.

    Asik

  • Tech Issues Solved: 14
  • Joined: 26-October 05

Posted 02 October 2013 - 22:30

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://wanderingcode...7/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!

 



#12 +Karl L.

Karl L.

    xorangekiller

  • Tech Issues Solved: 15
  • Joined: 24-January 09
  • Location: Virginia, USA
  • OS: Debian Testing

Posted 02 October 2013 - 22:46

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!



#13 Torolol

Torolol

  • Joined: 24-November 12

Posted 04 October 2013 - 06:57

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.

#14 The_Decryptor

The_Decryptor

    STEAL THE DECLARATION OF INDEPENDENCE

  • Tech Issues Solved: 5
  • Joined: 28-September 02
  • Location: Sol System
  • OS: iSymbian 9.2 SP24.8 Mars Bar

Posted 04 October 2013 - 07:14

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)



#15 OP Joni_78

Joni_78

    Neowinian Senior

  • Joined: 19-April 04
  • Location: Finland
  • OS: Windows 8 Pro with Media Center, OS X Mavericks 10.9.4
  • Phone: Nokia Lumia 920

Posted 05 October 2013 - 14:53

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;