23

为什么任何数据类型的范围在消极方面比积极方面更大?

例如,如果是整数:

Turbo C中,它的范围是-32768to 32767,对于Visual Studio,它是-2147483648to 2147483647.

其他数据类型也会发生同样的情况......

[UPD:为Visual Studio设置适当的限制值]

4

5 回答 5

51

因为数字的存储方式。带符号的数字使用称为“二进制补码表示法”的东西存储。

请记住,所有变量都有一定数量的位。如果其中最重要的一位,即左边的一位,是 0,则该数字为非负数(即正或零),其余位仅表示该值。

但是,如果最左边的位是 1,则该数字为负数。数字的真实值可以通过从表示的整数中减去 2^n 获得(作为无符号量,包括最左边的 1),其中 n 是变量具有的位数。

由于数字的实际值(“尾数”)只剩下 n - 1 位,因此可能的组合为 2^(n - 1)。对于正数/零数,这很容易:它们从 0 变为 2^(n - 1) - 1。 -1 是为了说明零本身——例如,如果你只有四种可能的组合,那些组合将代表 0、1、2 和 3(注意有四个数字):它从 0 变为 4 - 1。

对于负数,请记住最左边的位是 1,因此表示的整数介于 2^(n - 1) 和 (2^n) - 1 之间(括号在那里非常重要!)。但是,正如我所说,您必须带走 2^n 才能获得数字的实际值。2^(n - 1) - 2^n 是 -(2^(n - 1)),并且 ((2^n) - 1) - 2^n 是 -1。因此,负数的范围是 -(2^(n - 1)) 到 -1。

将所有这些放在一起,您会得到 -2^(n - 1) 到 2^(n - 1) - 1。如您所见,上限得到 -1,而下限没有。

这就是为什么负数比正数多一个的原因。

于 2013-09-01T12:11:53.553 回答
20

C 要求的最小范围实际上是 -32767 到 32767,因为它必须满足二进制补码、二进制补码和负数的符号/幅度编码,所有这些都是 C 标准允许的。有关数据类型的最小范围的详细信息,请参阅Annex E, Implementation limitsC11(和 C99)。

您的问题仅与二进制补码变体有关,原因很简单。使用 16 位,您可以表示 2 16(或 65,536)个不同的值,并且零必须是其中之一。因此剩下奇数个值,其中大多数(一个)是负值:

 1 thru  32767  = 37267 values
 0              =     1 value
-1 thru -32768  = 32768 values
                  -----
                  65536 values

一个的补码和符号幅度编码都允许负零值(以及正零),这意味着非零数可用的位模式减少了,因此您在标准中找到的最小范围减小.

 1 thru  32767  = 37267 values
 0              =     1 value
-0              =     1 value
-1 thru -32767  = 32767 values
                  -----
                  65536 values

二进制补码实际上是一种漂亮的编码方案,因为可以使用相同的简单硬件将正数和负数相加。其他编码方案往往需要更复杂的硬件来完成相同的任务。

有关二进制补码如何工作的更完整说明,请参阅维基百科页面

于 2013-09-01T12:14:16.550 回答
8

因为范围包括零。一个 n 位整数可以表示的不同值的数量是 2^n。这意味着一个 16 位整数可以表示 65536 个不同的值。如果是无符号 16 位整数,则可以表示 0-65535(含)。有符号整数的约定是表示 -32768 到 32767、-214748368 到 214748367 等。

于 2013-09-01T12:11:14.507 回答
0

使用 2s 补码,负数被定义为按位不加 1,这将给定位数的可能数字的范围在负侧减少 1。

于 2013-09-01T12:11:05.937 回答
0

通常,由于使用二进制补码系统来存储负值,当您翻转整数上的符号位时,它会偏向负数。

范围应为:-(2^(n-1)) - ((2^(n-1)-1)

于 2013-09-01T12:11:49.653 回答