永远递增,你会得到-2147483648?
出于一个我不想解释的聪明而复杂的原因(因为它涉及以一种极其丑陋和黑客的方式制作计时器),我编写了一些类似这样的 C# 代码:
int i = 0;
while (i >= 0) i++; //Should increment forever
Console.Write(i);
我希望程序永远挂起或崩溃或者其他什么,但是,令我惊讶的是,在等待大约 20 秒左右后,我得到了这个输出:
-2147483648
嗯,编程教会了我很多东西,但我仍然无法理解为什么不断增加一个数字会导致它最终变成负数。 .这是怎么回事?
For a clever and complicated reason that I don't really want to explain (because it involves making a timer in an extremely ugly and hacky way), I wrote some C# code sort of like this:
int i = 0;
while (i >= 0) i++; //Should increment forever
Console.Write(i);
I expected the program to hang forever or crash or something, but, to my surprise, after waiting for about 20 seconds or so, I get this ouput:
-2147483648
Well, programming has taught me many things, but I still cannot grasp why continually incrementing a number causes it to eventually be negative...what's going on here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
在 C# 中,内置整数由预定义长度的位值序列表示。对于基本
int
数据类型,长度为 32 位。由于 32 位只能表示 4,294,967,296 个不同的可能值(因为这是 2^32),因此显然您的代码不会随着值的不断增加而永远循环。由于
int
可以同时保存正数和负数,因此必须以某种方式对数字的符号进行编码。这是用第一位完成的。如果第一位是 1,则该数为负数。以下是以十六进制和十进制形式排列在数轴上的 int 值:
正如您从该图表中看到的,表示最小可能值的位是通过将最大可能值加 1 得到的,同时忽略符号位的解释。当以这种方式添加有符号数时,称为“整数溢出”。是否允许整数溢出或将其视为错误,可以使用 C# 中的
checked
和unchecked
语句进行配置。默认值是未选中的,这就是为什么没有发生错误,但你的程序中出现了那个疯狂的小数字。此表示称为2 的补码。
In C#, the built-in integers are represented by a sequence of bit values of a predefined length. For the basic
int
datatype that length is 32 bits. Since 32 bits can only represent 4,294,967,296 different possible values (since that is 2^32), clearly your code will not loop forever with continually increasing values.Since
int
can hold both positive and negative numbers, the sign of the number must be encoded somehow. This is done with first bit. If the first bit is 1, then the number is negative.Here are the int values laid out on a number-line in hexadecimal and decimal:
As you can see from this chart, the bits that represent the smallest possible value are what you would get by adding one to the largest possible value, while ignoring the interpretation of the sign bit. When a signed number is added in this way, it is called "integer overflow". Whether or not an integer overflow is allowed or treated as an error is configurable with the
checked
andunchecked
statements in C#. The default is unchecked, which is why no error occured, but you got that crazy small number in your program.This representation is called 2's Complement.
该值溢出了 32 位整数存储的正范围,到达
0xFFFFFFFF
,即十进制的 -2147483648。这意味着 31 位整数会溢出。有人指出,如果您使用 unsigned int,您会得到不同的行为,因为第 32 位不用于存储数字的符号。
The value is overflowing the positive range of 32 bit integer storage going to
0xFFFFFFFF
which is -2147483648 in decimal. This means you overflow at 31 bit integers.It's been pointed out else where that if you use an unsigned int you'll get different behaviour as the 32nd bit isn't being used to store the sign of of the number.
您遇到的是整数溢出。
What you are experiencing is Integer Overflow.
int
是有符号整数。一旦超过最大值,它就会从最小值(较大的负数)开始并逐渐向 0 迈进。使用
uint
重试,看看有什么不同。int
is a signed integer. Once past the max value, it starts from the min value (large negative) and marches towards 0.Try again with
uint
and see what is different.像这样尝试:
并解释结果
Try it like this:
And explain the results
其他人一直在说什么。如果您想要永远持续下去的东西(我不会评论为什么您需要这种东西),请使用 System.Numerics 命名空间中的 BigInteger 类 (.NET 4+)。您可以与任意大的数字进行比较。
What the others have been saying. If you want something that can go on forever (and I wont remark on why you would need something of this sort), use the BigInteger class in the System.Numerics namespace (.NET 4+). You can do the comparison to an arbitrarily large number.
它与正数和负数如何真正存储在内存中(位级别)有很大关系。
如果您有兴趣,请观看此视频:编程范式,时间为 12:25 及以后。非常有趣,你会明白为什么你的代码会这样运行。
It has a lot to do with how positive numbers and negative numbers are really stored in memory (at bit level).
If you're interested, check this video: Programming Paradigms at 12:25 and onwards. Pretty interesting and you will understand why your code behaves the way it does.
发生这种情况是因为当变量“i”达到最大 int 限制时,下一个值将是负值。
This happens because when the variable "i" reaches the maximum int limit, the next value will be a negative one.
我希望这听起来不像是自作聪明的建议,因为它的本意是好的,而不是尖刻的。
您要求我们描述整数数据类型的基本行为。
任何计算机科学课程的第一年都会介绍数据类型,这是有原因的,它对于理解事情如何以及在哪里可能出错确实非常重要(如果意外导致意外行为,即您可能已经看到上述行为如何导致意外行为,即错误)您的申请)。
我的建议是,获取计算机科学一年级的阅读材料 + Knuth 的开创性著作“计算机编程的艺术”,花费大约 500 美元,你将拥有成为一名优秀程序员所需的一切,比整个大学课程便宜得多;- )
I hope this does not sound like smart-ass advice, because its well meant, and not meant to be snarky.
What you are asking is for us to describe that which is pretty fundamental behaviour for integer datatypes.
There is a reason why datatypes are covered in the 1st year of any computer science course, its really very fundamental to understanding how and where things can go wrong (you can probably already see how the behaviour above if unexpected causes unexpected behaviour i.e. a bug in your application).
My advice is get hold of the reading material for 1st year computer science + Knuth's seminal work "The art of computer pragramming" and for ~ $500 you will have everything you need to become a great programmer, much cheaper than a whole Uni course ;-)