【问题标题】:Why is the maximum value of an unsigned n-bit integer 2ⁿ-1 and not 2ⁿ?为什么无符号 n 位整数的最大值是 2ⁿ-1 而不是 2ⁿ?
【发布时间】:2011-08-11 21:46:00
【问题描述】:

n-bit 整数的最大值为 2n-1。为什么我们有“负1”?为什么最大值不只是 2n

【问题讨论】:

标签: integer programming-languages numeric-limits


【解决方案1】:

在大多数编程语言中整数是有符号值(参见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)

【讨论】:

    【解决方案2】:

    为什么我们有“负 1”?

    只要回答这个问题:1 位整数的最大值是多少

    一位整数只能存储两个(21)个值:01。最后一个值为 12 = 110

    两位整数只能存储四个(22)个值:000110和@ 987654326@。最后一个值为 112 = 310

    因此,当整数可以存储N时,最后一个值将是N-1,因为计数是从开始的。

    n 位整数可以存储2n 值。最后是2n-1

    示例: 一个字节可以存储28 (256) 个值。第一个是0,最后一个是255

    为什么最大值不只是 2n?

    因为计数是从零开始的。查看任何n 位整数的第一个值。
    例如字节:00000000

    如果:
    00000001 表示 2
    00000000 表示 1,这将非常令人困惑

    不会? ;-)

    【讨论】:

      【解决方案3】:

      因为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

      等等。

      【讨论】:

        【解决方案4】:

        如果我问你可以放入一个 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?

        【讨论】:

          【解决方案5】:

          这是因为在计算中,数字从0 开始。因此,例如,如果您有 32 个地址行(232 个可寻址字节),它们将在[0, 2^32) 范围内。

          【讨论】:

            【解决方案6】:

            在大多数编程语言中,0 也是一个数字

            【讨论】:

            • 取决于你说的是整数还是自然数;)
            • @Russel 好吧,即使对于自然数 0 也经常被包括在内,所以甚至数学家都没有同意这一点(但实际上它只是那里更有用的数字之一 - 如果我们应该摆脱27或其他:p)
            • @RussellTroywest Peano 和 Frege 告诉我们什么是自然数,当然它们是从 0 开始的。尽管如此,在某些情况下使用和引用集合 N \ {0} 是可以理解的作为“自然数”。
            【解决方案7】:

            从 0 到 N 的数字不是 N。它们是 N+1。这对大多数人来说并不明显,因此许多程序都有错误,因为如果这个原因。

            【讨论】:

              【解决方案8】:

              2^32 二进制:

              1 00000000 00000000 00000000 00000000
              

              2^32 - 1 二进制:

              11111111 11111111 11111111 11111111
              

              如您所见,2^32 采用33 位,而2^32 - 132 位整数的最大值。

              这里看似“off-by-one”错误的原因是最低位表示一,而不是二。所以 first 位实际上是 2^0second 位是 2^1,等等...

              【讨论】:

              • 如果我有 64 位机器和操作系统和 Java 怎么办?它是否增加到 2 ^ 64 - 1 ??
              【解决方案9】:

              -1 是因为整数从 0 开始,但我们的计数从 1 开始。

              因此,2^32-1 是 32 位无符号整数(32 个二进制数字)的最大值2^32可能值的数量

              为了简化原因,请查看小数。 10^2-1 是 2 位十进制数 (99) 的最大值。因为我们直观的人工计数从 1 开始,但整数是从 0 开始的,所以10^2 是值的数量 (100)。

              【讨论】:

              • 如果我有 64 位机器和操作系统和 Java 怎么办?它是否增加到 2 ^ 64 - 1 ??
              • 平台是什么并不重要。您可以存储在从 0 开始的 N 位无符号整数中的最大值始终为 2^N-1
              • @tenfour 因此对于有符号整数,它将是 2^N-2。我这样说对吗?
              • 有符号整数的最大值取决于整数的存储方式。很多时候,正面是 2^(n-1)-1,反面是 -2^(n-1),但您应该查阅您的语言/系统的文档。
              • 一般来说:基数和位数无关紧要。您可以在基于 B 的 N 位无符号整数中存储的最大值始终为 B^N-1
              【解决方案10】:

              在计算领域,我们从 0 开始计数。

              【讨论】:

                【解决方案11】:

                如果您刚开始编程,我建议您查看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] 范围内的整数。现在你可以去阅读那篇文章并了解不同的形式,以及表示负整数等。

                【讨论】:

                  【解决方案12】:
                  二进制中的

                  232 是一个后跟 32 个零,总共 33 位。这不适合 32 位 int 值。

                  【讨论】:

                  • 如果我有 64 位机器和操作系统和 Java 怎么办?它是否增加到 2 ^ 64 - 1 ??
                  • @HardikThaker - 是的,确实如此。 (实际上,在 Java 中,Integer.MAX_VALUE--对于 32 位整数--是 2^31 - 1 和 Long.MAX_VALUE--对于 64 位整数--是 2^63 - 1,因为符号位是保留的。)
                  • @Ted Hopp 什么符号位?没有符号位这样的东西。
                  • @Ingo - “没有符号位这样的东西” 嗯?在我知道的大多数语言中,确实有一个符号位。 Java(这是我在评论中特别谈到的)对大多数整数类型(char 除外)使用有符号的二进制补码表示。请参阅the Wikipedia article on Two's complement,您可以阅读有关符号位的所有信息。另请参阅the Wikipedia article on Sign bit
                  • @TedHopp 用语言签名?不见得。您可以将最左边的位称为符号位,因为选择了表示,因此如果您使用有符号整数,则该位表示负号。您也可以将最右边的位称为 odd bit,因为它表示奇数值。但他们都不是“保留”的。事实上,即使在 Java 中,您也可以使用符号位进行(一些)无符号计算。例如 (2* 0x40000001 - 3) 应该给你 MAXINT。请注意,乘法产生 0x80000002,并使用符号位。
                  猜你喜欢
                  • 2020-06-26
                  • 1970-01-01
                  • 2016-04-23
                  • 1970-01-01
                  • 2015-10-07
                  • 1970-01-01
                  • 2015-10-15
                  • 1970-01-01
                  • 2019-11-09
                  相关资源
                  最近更新 更多