• Advertisement
Sign in to follow this  

Signed Rotation

This topic is 867 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Advertisement
Disclaimer: I don't know any C#, but I still think I can help.

Cast to unsigned int, then use (value << count) | (value >> (32 - count)), then cast back to signed int.

I'm curious though: Why do you want to rotate the bits of a signed integer? It doesn't seem like the most natural operation...

Share this post


Link to post
Share on other sites

Wouldn't the type conversion mess up the data at all?  For example, suppose I had a negative number, and when I convert it into a uint, it will become 0, won't it?

 

Well let's say I have my reasons but frankly they're hard to explain, with a whole lot of technical junk and honestly I'm in a hurry, but thanks.

Share this post


Link to post
Share on other sites

Wouldn't the type conversion mess up the data at all?  For example, suppose I had a negative number, and when I convert it into a uint, it will become 0, won't it?
 
Well let's say I have my reasons but frankly they're hard to explain, with a whole lot of technical junk and honestly I'm in a hurry, but thanks.


No, casting will probably preserve the bit pattern, and reinterpret the number by taking the most-significant bit to mean +2^31 instead of -2^31.

See the section "Integral conversions" in this page: https://msdn.microsoft.com/en-us/library/aetzh118.aspx

Share this post


Link to post
Share on other sites

Wouldn't the type conversion mess up the data at all?  For example, suppose I had a negative number, and when I convert it into a uint, it will become 0, won't it?
 
Well let's say I have my reasons but frankly they're hard to explain, with a whole lot of technical junk and honestly I'm in a hurry, but thanks.


Casting between signed and unsigned just changes the interpretation of the underlying data, no actualy changes to the data happens. Signed numbers use 2s complement so negative numbers in signed turn into a large positive number which depends on how many bits are in the number.

EDIT: Alvaro beat me to it Edited by HappyCoder

Share this post


Link to post
Share on other sites
Conveniently, signed-to-unsigned conversions do not clamp the old value to the new range of supported values, but just reinterpret the data as an unsigned integer.  From MSDN:
 

Objects of signed integral types can be converted to corresponding unsigned types. When these conversions occur, the actual bit pattern does not change; however, the interpretation of the data changes.

 
Further, I'm pretty sure that the integer data sizes and bit patterns of .NET integers are well defined (in contrast to languages like C++ where 32-bit width or 2's complement representation of signed integers can't be relied upon portably).  So if you you really want to preserve that sign bit, and rotate everything else, you can do so (untested):
int rotated = (value & 0x80000000) | ((value << count) | (value >> (31 - count))) & 0x7FFFFFFF;

EDIT: Alvaro beat me to it

EDIT: Alvaro and HappyCoder both beat me to it. :-) Edited by Andy Gainey

Share this post


Link to post
Share on other sites

Why the two constants?  Also, I don't remember which happens first, the | or the &?  I generally put them in parentheses to avoid confusion so I don't really have to know.  But it's the... &, right?

Share this post


Link to post
Share on other sites
Yes, first priority goes to &. However you can use parentheses to give priority and to better visualize the order of priority.

If you mean the constant 0x80000000, this is the maximum value that can have a signed int. You need it to do the bitwise & with the value chosen by you, so you "cut" the value on the range of unsigned.

Share this post


Link to post
Share on other sites

The purpose of the first constant and the & with value is to get the sign bit and nothing else (every other bit is forced to be 0).  The second constant does the opposite; it makes sure that the half of the expression after the | does not contain the sign bit (that bit is always forced to 0).  Then when the two halves are or-ed together, their bits are guaranteed to not overlap or interfere.  So we're basically merging the original sign bit with the newly rotated non-sign bits.

 

I forgot to mention it yesterday, but keep in mind that negative numbers are almost always represented using two's complement, which means that simply flipping the sign bit does not simply flip the sign of the number while otherwise leaving its value unchanged.  Depending on how you use the results of a sign-preserving rotation, this might fail to produce the values you are looking for.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement