C - 转换为2s补码

时间:2010-04-05 21:50:45

标签: c twos-complement

我决定这样做

  • 翻转数字0 = 1,1 = 0
  • 将1添加到LSB
  • if carry,循环直到array [i] == 0

但我坚持到最后一点;我怎么能在条件循环中说呢?

5 个答案:

答案 0 :(得分:2)

你在谈论扩展算术。大多数处理器都会在每次加法操作时产生进位和溢出,但C不提供对它们的访问。

你的问题是,随着数字变大,数字会变长。如果你在最后一点,你需要执行,你还需要一点!这意味着您需要重新分配位数组(如果您使用的是数组)。

当然,一个更实用的解决方案是使用本机整数而不是单个位,因为你的处理器已经很好地处理了二进制补码。然后,您知道如果原始数字等于(unsigned) -1,则添加一个会导致结转。根本问题仍然存在;如果你需要执行最后unsigned,你需要分配另一个。

答案 1 :(得分:0)

因此,您将数字存储为一个表示位的整数数组。 在您附加的代码示例中,您忘记增加 i 变量,并检查它是否超出了数组的大小。

你可以写这样的东西(我假设数组的大小 5 ):

for (i = 0; i < 5; i++)
{
    if (array1[i] == 1)
        array1[i] = 0;
    else // we found a 0
        array1[i] = 1;
        break;
}

答案 2 :(得分:0)

我不太清楚你在做什么,但也许这会有所帮助:

#define countof(x) (sizeof(x) / sizeof(x[0]))

// an 8-bit number
int byte[8] = {0, 1, 1, 0, 1, 1, 1, 0}; // 1 = on, 0 = off

// flip all bits
for (size_t i = 0; i < countof(byte); ++i)
{
    byte[i] = !byte[i];
}

// add one
for (size_t i = 0; i < countof(byte); ++i)
{
    if (byte[i]) // if on
    {
        byte[i] = 0; // "add 1, reset to zero", and carry (no break)
    }
    else // if off
    {
        byte[i] = 1; // turn on
        break; // nothing to carry, stop adding
    }

}

(我不知道如何在不解释代码的情况下将你推向正确的方向,对不起。我认为你已经足够接近了,这仍然有用。)

您可以看到,当您添加一个时,如果该位已经为1,则将其重置为零,然后沿着这些位继续。如果该位为零,则将其设置为1,然后退出循环。 (什么都没有,所以我们已经完成了添加。)

希望有所帮助。顺便说一句,你会注意到这些位在上面的代码中“向后”存储。 LSB位于索引0。

答案 3 :(得分:0)

你可以用更简单的方式做2的补码:   

       
  • 保持不变直到找到1。
  •    
  • 在获得第一个1之后,将下一个0到1和1翻转到Zeros并继续这样做。如果MSB变为0,则表示发生了溢出。

您可以自己检查算法的有效性。实施应该如下:

// an 8-bit number
int number[8] = {0, 1, 1, 1, 0, 1, 0, 0};
int i;
bool gotFirstOne = false;

// flip bits after you first encountered an 1
for (i = 0; i < 8; i++)
{
   if(gotFirstOne == false){
       if(number[i] == 1) {
           gotFirstOne = true;
       }
   }
   else {
       number[i] = !number[i];
   }

}

if(number[7] == 0) {
    printf("Overflow occurred");
}

干杯!!!!

答案 4 :(得分:0)

我对2的补码的答案,记住这是12位补码,你可以根据你的要求改变掩码或整数类型。这是完美的,也可以使用宏。

int twos_compliment(unsigned short a)
{
    int result;
    result = 0x0FFF&a;
    result = (((result&0x800)?(0<<11):(1<<11))|((result&0x400)?(0<<10):(1<<10))
            |((result&0x200)?(0<<9):(1<<9))|((result&0x100)?(0<<8):(1<<8))
            |((result&0x080)?(0<<7):(1<<7))|((result&0x040)?(0<<6):(1<<6))
            |((result&0x020)?(0<<5):(1<<5))|((result&0x010)?(0<<4):(1<<4))
            |((result&0x008)?(0<<3):(1<<3))|((result&0x004)?(0<<2):(1<<2))
            |((result&0x002)?(0<<1):(1<<1))|((result&0x001)?0:1));
    return result=result+1;
}