我想将一个位掩码应用于一个数字,该数字将模拟2的补码编码的有符号32位整数的绝对值函数。到目前为止,我有
int absoluteValue(int x) {
int sign = x >> 31; //get most significant byte...all 1's if x is < 0, all 0's if x >= 0
int negated = (~x + 1) & sign; //negates the number if negative, sets to 0 if positive
//what should go here???
}
我是朝着正确的方向前进的吗?我不确定从哪里开始(主要是如何应用掩码来保持原始的正值)。我也不想使用任何条件语句
答案 0 :(得分:3)
奇怪的问题。
怎么样?return (negated << 1) + x;
因此,这使得:
int absoluteValue(int x) {
int sign = x >> 31; //get most significant byte...all 1's if x is < 0, all 0's if x >= 0
int negated = (~x + 1) & sign; //negates the number if negative, sets to 0 if positive
return (negated << 1) + x;
}
答案 1 :(得分:1)
最后一部分
negated = (~x + 1) & sign;
错了,你要得到1或0,你必须用all创建一个掩码 前31位为0,只有最后一位为0或1。
假设您的目标是使用2处理32位整数 补充,你可以这样做:
#include <stdio.h>
// assuming 32bit, 2 complement
int sign_inverse(int n)
{
int mask = ~n & 0x80000000U;
if(n == 0)
mask = 0;
return (~n + 1) | mask;
}
int main(void)
{
int a = 5;
int b = -4;
int c = 54;
int d = 0;
printf("sign_inverse(%d) = %d\n", a, sign_inverse(a));
printf("sign_inverse(%d) = %d\n", b, sign_inverse(b));
printf("sign_inverse(%d) = %d\n", c, sign_inverse(c));
printf("sign_inverse(%d) = %d\n", d, sign_inverse(d));
return 0;
}
但是对于0的情况你需要至少1 if
,因为0的掩码是0x80000000
。
这个输出是:
$ ./b
sign_inverse(5) = -5
sign_inverse(-4) = 4
sign_inverse(54) = -54
sign_inverse(0) = 0
答案 2 :(得分:1)
请注意,我们无法保证两个补码的表示形式,也不保证操作符>>
对签名值的行为,其中结果为&#34;&#34;#34;填充&#34;使用1
- 位是实现定义的(参见,例如,cppreference.com/arithmetic operations):
对于负LHS,LHS的值>&gt; RHS是实施定义的 在大多数实现中,这执行算术右移 (这样结果仍然是负面的)。因此在大多数实现中, 右移一个带符号的LHS用新的高阶位填充 原始符号位(如果它是非负的则为0,如果为非则为1) 负)。
但是如果你把它当作给定的,如果你只想使用位操作和运算符+
,那么你已经朝着正确的方向前进了。
唯一的一点是你应该考虑你创建的面具(即你的sign
),因为只有在x
为负的情况下才切换x
的位。您可以通过XOR运算符实现此目的,如下所示:
int x = -3000;
unsigned int mask = x >> 31;
int sign = mask & 0x01;
int positive = (x^mask) + sign;
printf("x:%d mask:%0X sign:%d positive:%d\n",x,mask,sign,positive);