将负数转换为正数但保持正数不变

时间:2018-04-14 18:55:28

标签: c bit-manipulation

我想将一个位掩码应用于一个数字,该数字将模拟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???
}

我是朝着正确的方向前进的吗?我不确定从哪里开始(主要是如何应用掩码来保持原始的正值)。我也不想使用任何条件语句

3 个答案:

答案 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);