How to convert from sign-magnitude to two's complement

1

How would I convert from sign-magnitude to two's complement. I don't know where to start. Any help would be appreciated. I can only use the following operations:!,~,|,&,^,+,>>,<<.

/*
 * sm2tc - Convert from sign-magnitude to two's complement
 *   where the MSB is the sign bit
 *   Example: sm2tc(0x80000005) = -5.
 *   
 */
int sm2tc(int x) {

return 2;
}
c
bit-manipulation
asked on Stack Overflow Feb 17, 2014 by user3316874

5 Answers

3

You can convert signed-magnitude to two's complement by subtracting the number from 0x80000000 if the number is negative. This will work for a 32-bit integer on a machine using two's complement to represent negative values, but if the value is positive this will result in a two's complement negation. A right shift of a two's complement negative number will shift in one's, we can utilize this to make a mask to select between the original value, or the conversion of a signed-magnitude negative value to a two's complement negative value.

int sm2tc(int x) {
  int m = x >> 31;
  return (~m & x) | (((x & 0x80000000) - x) & m);
}
answered on Stack Overflow Feb 18, 2014 by Apriori
1

There you go.

uint32_t sm2tc(uint32_t x)
{
        return (x & 0x80000000)
                ? ((~(x & 0x7fffffff)) + (uint32_t)1)
                : x;
}
answered on Stack Overflow Feb 17, 2014 by Daniel Kamil Kozar
1

Interestingly, the conversion between the two formats is symmetrical, so you need only one conversion function to swap from one format to the other. Here is the complete conversion without relying on any conditionals:

uint32_t convertSignRepresentation(uint32_t in) {
    uint32_t mask = -(in >> 31);
    return mask&0x80000000-in | ~mask&in;
}

The technique I used here is essentially replacing the conditional operator in

uint32_t convertSignRepresentation(uint32_t in) {
    return (in >> 31) ? 0x80000000-in : in;
}

by a bitmask of only zeros or ones to select the correct resulting value.


Please note, that 0x80000000 (either smallest possible value, or negative zero) is projected to positive zero, and cannot be recovered. So convertSignRepresentation(converSignRepresentation(0x80000000)) yields zero instead of 0x80000000. This might give nasty surprises. It might be avoided in theory by mapping 0x80000000 onto itself, but that is not as easy to do and has even nastier surprises...


Edit:
A comment pointed out that subtraction was not on the list of allowed operators, even though addition is. I don't know whether this was deliberate or a mistake. Anyways, the operation -x can be written as ~x + 1. With this, the code becomes:

uint32_t convertSignRepresentation(uint32_t in) {
    uint32_t mask = ~(in >> 31) + 1;
    return mask&0x80000001+~in | ~mask&in;
}
answered on Stack Overflow Feb 17, 2014 by cmaster - reinstate monica • edited Feb 18, 2014 by cmaster - reinstate monica
0

Signed Numbers are 8 bit quantities with the least significant 7 bits representing the magnitude and the most significant bit indicating the sign. 0 in this bit indicates the number is positive, and 1 indicates it is negative. There is no magnitude information in this 8th bit-just the sign.

To convert a negative signed number to two's complement, first set the 8th bit to zero. Then invert all 8 bits. Finally add 1. An example follows:

Signed Number:

10001111

set the 8th bit to zero: (use & operator)

00001111

invert all 8 bits: (use bitwise-complement operator)

11110000

finally, add 1; resulting in the final two's complement number: (use + operator)

11110001

If the 8th bit is 0, indicating that the signed number is positive, the number requires no conversion. It's two's complement representation is the same as the signed magnitude representation.

answered on Stack Overflow Feb 17, 2014 by Dinesh • edited Feb 17, 2014 by Utkan Gezer
0

To convert from Sign Magnitude x to Two's Complement y:

1) On a two's complement machine.
2) Use only !,~,|,&,^,+,>>,<<
3) Does not use ?:, -, *, /
4) Does not assume 4-byte int
5) Work with all Sign Magnitude including +0 and -0

#include <limits.h>
int sm2tc(int x) {
  int sign = x & INT_MIN;
  int negmask = UINT_MAX + !sign;
  return (x & ~negmask) | (negmask & ((~x + 1)^INT_MIN));
}
answered on Stack Overflow Feb 17, 2014 by chux - Reinstate Monica • edited Feb 18, 2014 by chux - Reinstate Monica

User contributions licensed under CC BY-SA 3.0