K& R练习3-4:二进制表示的负数

时间:2016-08-31 20:36:54

标签: c binary bits

我很难理解这个练习:

  

在二进制补码表示中,我们的itoa版本没有   处理最大的负数,即n的值等于 - (2 ^(wordsize-1))。解释为什么不。修改它以正确打印该值,无论它运行的机器如何。

以下是itoa最初的样子:

void reverse(char s[], int n)
{
  int toSwap;
  int end = n-1;
  int begin = 0;

  while(begin <= end) // Swap the array in place starting from both ends.
    {
      toSwap = s[begin];
      s[begin] = s[end];
      s[end] = toSwap;

      --end;
      ++begin;
    }
}

// Converts an integer to a character string.
void itoa(int n, char s[])
{
  int i, sign;
  if ((sign = n) < 0)
    n = -n;
  i = 0;
  do
    {
      s[i++] = n % 10 + '0';
    } while ((n /= 10) > 0);

  if (sign < 0)
    s[i++] = '-';
  s[i] = '\0';
  reverse(s, i);
}

我找到了这个答案,但我不明白这个解释: http://www.stevenscs.com/programs/KR/ $ progs的/ KR-EX3-04.html

  

因为一个单词可以容纳的最大负数的绝对值大于最大正数的绝对值,所以在iota中早期设置正数为负数的语句会破坏其值。

他们是否说负号由于符号而包含的位数多于没有符号的正数?为什么乘以-1会影响大负数的存储方式?

2 个答案:

答案 0 :(得分:0)

问题是,如果n是最大的负数,当你做n = -n时你得到0,因为你不能代表一个大的正数。

解决方案可以是将正数保存在一个长整数中。

答案 1 :(得分:0)

在两个补码表示中,您可以表示的值范围是-2n-12n-1-1。因此,对于8位,您可以表示-128到127范围内的值。这是短语的含义,&#34;单词可容纳的最大负数大于最大的正数。&#34;

只用3位进行说明,使其更清晰:

Value    Bits
-----    ----
    0    000
    1    001
    2    010
    3    011
   -4    100
   -3    101
   -2    110
   -1    111

对于3位,我们无法在两个补码中表示 4,因此n = -n;赢了#t给我们预期的结果 1 。这就是上述原始atoi实施无法处理INT_MIN的原因。

<小时/>

  1. 有符号整数溢出的行为是 undefined ,这意味着没有固定的结果。