5

出于一个我不想解释的聪明而复杂的原因(因为它涉及以极其丑陋和骇人听闻的方式制作计时器),我编写了一些类似这样的 C# 代码:

int i = 0;
while (i >= 0) i++; //Should increment forever
Console.Write(i);

我希望程序永远挂起或崩溃或其他什么,但令我惊讶的是,在等待大约 20 秒左右后,我得到了这个输出:

-2147483648

好吧,编程教会了我很多东西,但我仍然无法理解为什么不断增加一个数字会导致它最终变成负数……这是怎么回事?

4

9 回答 9

12

在 C# 中,内置整数由预定义长度的位值序列表示。int对于长度为 32 位的基本数据类型。由于 32 位只能表示 4,294,967,296 个不同的可能值(因为那是 2^32),显然您的代码不会随着值的不断增加而永远循环。

由于int可以同时保存正数和负数,因此必须以某种方式对数字的符号进行编码。这是用第一位完成的。如果第一位为 1,则该数为负数。

以下是十六进制和十进制数列上的 int 值:

 Hexadecimal        Decimal
 -----------    -----------
 0x80000000     -2147483648
 0x80000001     -2147483647
 0x80000002     -2147483646
    ...              ...
 0xFFFFFFFE              -2
 0xFFFFFFFF              -1
 0x00000000               0
 0x00000001               1
 0x00000002               2
     ...             ...
 0x7FFFFFFE      2147483646
 0x7FFFFFFF      2147483647

从这个图表中可以看出,代表最小可能值的位是通过将最大可能值加 1 得到的,同时忽略符号位的解释。以这种方式添加有符号数时,称为“整数溢出”。是否允许整数溢出或将其视为错误可以使用 C# 中的checkedandunchecked语句进行配置。默认是未选中的,这就是为什么没有发生错误,但是你在你的程序中得到了那个疯狂的小数字。

这种表示称为2's Complement

于 2011-05-31T22:20:12.750 回答
8

该值溢出了 32 位整数存储的正范围,0xFFFFFFFF十进制为 -2147483648。这意味着您在 31 位整数处溢出。

有人指出,如果你使用无符号整数,你会得到不同的行为,因为第 32 位没有被用来存储数字的符号。

于 2011-05-31T22:07:39.450 回答
2

您正在经历的是Integer Overflow

在计算机编程中,当算术运算试图创建一个大于可用存储空间内可以表示的数值时,就会发生整数溢出。例如,将可表示的最大值加 1 构成整数溢出。在这些情况下,最常见的结果是存储结果的最低可表示位(结果被称为回绕)。

于 2011-05-31T22:05:39.350 回答
2

int是有符号整数。一旦超过最大值,它就会从最小值(大的负数)开始向 0 前进。

再试一次,uint看看有什么不同。

于 2011-05-31T22:07:23.643 回答
2

试试这样:

int i = 0;
while (i >= 0) 
   checked{ i++; } //Should increment forever
Console.Write(i);

并解释结果

于 2011-05-31T22:07:31.750 回答
2

其他人一直在说什么。如果你想要一些可以永远持续下去的东西(我不会评论你为什么需要这种东西),请使用 System.Numerics 命名空间(.NET 4+)中的BigInteger类。您可以与任意大的数字进行比较。

于 2011-05-31T22:08:17.663 回答
0

发生这种情况是因为当变量“i”达到最大 int 限制时,下一个值将是负值。

于 2011-05-31T22:08:09.207 回答
0

它与正数和负数如何真正存储在内存中(在位级别)有很大关系。

如果您有兴趣,请观看此视频: 12:25 及以后的编程范式。非常有趣,您将理解为什么您的代码会以这种方式运行。

于 2011-05-31T22:12:58.927 回答
-1

我希望这听起来不像是聪明人的建议,因为它的本意是好的,而不是刻薄的。

您要求我们描述整数数据类型的基本行为。

任何计算机科学课程的第一年都会涵盖数据类型是有原因的,这对于理解事情如何以及在哪里出错是非常重要的(如果意外导致意外行为,您可能已经看到上述行为,即错误你的申请)。

我的建议是掌握一年级计算机科学的阅读材料 + Knuth 的开创性著作“计算机编程的艺术”,只需 500 美元,您就可以拥有成为一名优秀程序员所需的一切,比整个 Uni 课程便宜得多;- )

于 2011-05-31T22:28:52.583 回答