I need to convert from two\'s complement to sign-magnitude in C using only the operators
! ~ & ^ | + << >>
My approach is t
From http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs
int const mask = v >> 31;
unsigned int r = (v + mask) ^ mask;
Gives the absolute value (magnitude). If you wish to add the sign bit back simply mask and or the 32nd bit:
unsigned int s_M = r | (v & 0x80000000);
Or if you're looking for a one liner:
unsigned int s_M = ((v + (v >> 31)) ^ (v >> 31)) | (v & 0x80000000);
I'm not entirely sure what the output should be, but to obtain the magnitude you can do something like this:
int m = (a^(a>>31)) + sign;
Basically, shifting a negative number 31 bits to the right will make it all 1's, or 0xffffffff
, which you can then use to xor the input number and make it positive. As you correctly noted sign
needs to be added then for the correct result in that case.
If the input number was positive to begin with, the shift results in a zero and so the xor does nothing. Adding sign
in that case also doesn't do anything, so it results in the input number.
To get the last bit you could use mask operation
int last_bit = 32 bit integer & 0x80000000
o/p may be 0 or 0x80000000
if it is 0
just display the given number else you have to perform the following operations to represent in signed magnitude
1) Subtract 1 from the number
2) perform 1s complement on the resultant ( that is negation ~
)
3) Set the last bit of the resultant number
I mean ( ~ (num -`1) ) | 0x7fffffff
since your restricted not to use -
operator. Perform the 2's complement on -1
and add it to the num
.
To put it simple in one line
num & 0x80000000 ? printf("%d",(~(num+((~1)+1))) | 0x7fffffff) : printf("%d",num) ;
When you're converting from 2 complement, you should subtract 1, not add.