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