如何从符号量转换为二进制补码

时间:2014-02-17 18:51:02

标签: c bit-manipulation

我如何将符号幅度转换为二进制补码。我不知道从哪里开始。任何帮助,将不胜感激。 我只能使用以下操作:!,〜,|,&,^,+,>>,<<。

/*
 * 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;
}

5 个答案:

答案 0 :(得分:3)

如果数字为负,您可以通过从0x80000000中减去数字,将有符号幅度转换为二进制补码。这将适用于机器上的32位整数,使用二进制补码来表示负值,但如果该值为正,则将导致二进制补码否定。二进制补码负数的右移将在一个中移位,我们可以利用它来制作一个掩码,在原始值之间进行选择,或者将有符号幅度负值转换为二进制补码负值。

int sm2tc(int x) {
  int m = x >> 31;
  return (~m & x) | (((x & 0x80000000) - x) & m);
}

答案 1 :(得分:1)

你去。

uint32_t sm2tc(uint32_t x)
{
        return (x & 0x80000000)
                ? ((~(x & 0x7fffffff)) + (uint32_t)1)
                : x;
}

答案 2 :(得分:1)

有趣的是,两种格式之间的转换是对称的,因此您只需要一种转换功能即可从一种格式交换到另一种格式。以下是完全转换,不依赖于任何条件:

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

我在这里使用的技术基本上是替换

中的条件运算符
uint32_t convertSignRepresentation(uint32_t in) {
    return (in >> 31) ? 0x80000000-in : in;
}

仅使用0或1的位掩码来选择正确的结果值。


请注意,0x80000000(最小可能值或负零)被预测为正零,并且无法恢复。因此convertSignRepresentation(converSignRepresentation(0x80000000))产生零而不是0x80000000。这可能会带来令人讨厌的惊喜。理论上可以通过将0x80000000映射到自身来避免,但这并不容易做到,甚至有更多的惊喜......


编辑:
一条评论指出减法不在允许的运算符列表中,即使添加也是如此。我不知道这是故意还是错误。无论如何,操作-x可以写成~x + 1。有了这个,代码就变成了:

uint32_t convertSignRepresentation(uint32_t in) {
    uint32_t mask = ~(in >> 31) + 1;
    return mask&0x80000001+~in | ~mask∈
}

答案 3 :(得分:0)

有符号数是8位量,最低有效7位表示幅度,最高有效位表示符号。该位中的0表示该数字为正,1表示该数字为负。第8位没有幅度信息 - 只是符号。

要将带负数的有符号数转换为二进制补码,首先将第8位设为零。然后反转所有8位。最后添加1.示例如下:

签名号码:

10001111

将第8位设置为零:(使用&运算符)

00001111

反转所有8位:(使用bitwise-complement运算符)

11110000

最后,加1;得到最后两个补码:(使用+运算符)

11110001

如果第8位为0,表示带符号的数字为正数,则该数字不需要转换。它的二进制补码表示与带符号的幅度表示相同。

答案 4 :(得分:0)

要将Sign Magnitude x转换为Two's Complement y:

1)在双补机上 2)仅使用!,〜,|,&,^,+,>>,<<
3)不使用?:, - ,*,/
4)不假设4字节int
5)使用所有符号幅度,包括+0和-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));
}