【发布时间】:2011-08-11 21:46:00
【问题描述】:
n-bit 整数的最大值为 2n-1。为什么我们有“负1”?为什么最大值不只是 2n?
【问题讨论】:
标签: integer programming-languages numeric-limits
n-bit 整数的最大值为 2n-1。为什么我们有“负1”?为什么最大值不只是 2n?
【问题讨论】:
标签: integer programming-languages numeric-limits
在大多数编程语言中整数是有符号值(参见two's complement)。
例如,在 Java 和 .NET 中,整数的最左字节保留用于符号:
0 => 正数或零数1 => 负数那么32-bit数字的最大值被限制为231。再加上-1,我们得到 231 - 1。
为什么会出现-1?
看看更简单的无符号字节(8位)示例:
1 1 1 1 1 1 1 1
128 64 32 16 8 4 2 1 <-- the most right bit cannot represent 2
--- --------------------
128 + 127 = 255
正如其他人指出的那样,最右边的位可以有 1 的最大值,而不是 2,因为 0/1 值。
Int32.MaxValue = 2147483647 (.NET)
【讨论】:
为什么我们有“负 1”?
只要回答这个问题:1 位整数的最大值是多少?
一位整数只能存储两个(21)个值:0和1。最后一个值为 12 = 110
两位整数只能存储四个(22)个值:00、01、10和@ 987654326@。最后一个值为 112 = 310
因此,当整数可以存储N时,最后一个值将是N-1,因为计数是从零开始的。
n 位整数可以存储2n 值。最后是2n-1
示例:
一个字节可以存储28 (256) 个值。第一个是0,最后一个是255
为什么最大值不只是 2n?
因为计数是从零开始的。查看任何n 位整数的第一个值。
例如字节:00000000
如果:00000001 表示 200000000 表示 1,这将非常令人困惑
不会? ;-)
【讨论】:
因为0也表示。你可以表示的数字数量确实是2^n,n位,但是最大的数字是2^n-1,因为你必须从0开始计数,即每个位都设置为0。
对于 1 位:0、1
对于 2 位:0、1、2、3
对于 3 位:0、1、2、3、4、5、6、7
等等。
【讨论】:
如果我问你可以放入一个 2 位数字的最大值是多少,你会说是 102 (100) 还是 102-1 (99)?显然是后者。因此,如果我问你最大的n-digit 数字是多少,它会是 10n-1。但是为什么会有“-1”呢?很简单,因为我们可以将 0 在 2 位数字中也表示为 00(但每个人都只写 0)。
让我们将10 替换为任意基数b。因此,对于给定的基数 b,您可以表示的最大 n-digit 数字是 bn-1。使用 32 位 (n = 32) base-2 (b = 2) 数字,我们看到我们可以表示的最大值为 232-1。
另一种思考方式是使用较小的数字。假设我们有一个 1 位数字。你能告诉我它可以代表的最大值是 21 还是 21-1?
【讨论】:
这是因为在计算中,数字从0 开始。因此,例如,如果您有 32 个地址行(232 个可寻址字节),它们将在[0, 2^32) 范围内。
【讨论】:
在大多数编程语言中,0 也是一个数字。
【讨论】:
从 0 到 N 的数字不是 N。它们是 N+1。这对大多数人来说并不明显,因此许多程序都有错误,因为如果这个原因。
【讨论】:
2^32 二进制:
1 00000000 00000000 00000000 00000000
2^32 - 1 二进制:
11111111 11111111 11111111 11111111
如您所见,2^32 采用33 位,而2^32 - 1 是32 位整数的最大值。
这里看似“off-by-one”错误的原因是最低位表示一,而不是二。所以 first 位实际上是 2^0,second 位是 2^1,等等...
【讨论】:
-1 是因为整数从 0 开始,但我们的计数从 1 开始。
因此,2^32-1 是 32 位无符号整数(32 个二进制数字)的最大值。 2^32 是可能值的数量。
为了简化原因,请查看小数。 10^2-1 是 2 位十进制数 (99) 的最大值。因为我们直观的人工计数从 1 开始,但整数是从 0 开始的,所以10^2 是值的数量 (100)。
【讨论】:
2^N-1。
在计算领域,我们从 0 开始计数。
【讨论】:
如果您刚开始编程,我建议您查看signed number representations 上的这篇 wiki 文章
正如 Vicente 所说,您减去 1 的原因是因为 0 也是一个包含的数字。举个简单的例子,用 3 位可以表示以下非负整数
0 : 000
1 : 001
2 : 010
3 : 011
4 : 100
5 : 101
6 : 110
7 : 111
除此之外的任何内容都需要 3 位以上的数字。因此,您可以表示的最大数字是 2^3-1=7。因此,您可以将其扩展到任何n,并表示您可以表示[0,2^n -1] 范围内的整数。现在你可以去阅读那篇文章并了解不同的形式,以及表示负整数等。
【讨论】:
232 是一个后跟 32 个零,总共 33 位。这不适合 32 位 int 值。
【讨论】:
Integer.MAX_VALUE--对于 32 位整数--是 2^31 - 1 和 Long.MAX_VALUE--对于 64 位整数--是 2^63 - 1,因为符号位是保留的。)
char 除外)使用有符号的二进制补码表示。请参阅the Wikipedia article on Two's complement,您可以阅读有关符号位的所有信息。另请参阅the Wikipedia article on Sign bit。