什么是整数溢出错误?为什么我关心这样的错误?有哪些避免或预防的方法?
10 回答
当您尝试表达的数字大于整数类型可以处理的最大数字时,就会发生整数溢出。
如果你试图用一个字节来表示数字 300,就会出现整数溢出(最大值为 255)。两个字节中的 100,000 也是整数溢出(最大值为 65,535)。
您需要关心它,因为数学运算不会像您预期的那样运行。如果整数溢出,A + B 实际上并不等于 A 和 B 的总和。
您可以通过不首先创建条件来避免它(通常是通过选择足够大的整数类型以使其不会溢出,或者通过限制用户输入以免发生溢出)。
解释它的最简单方法是用一个简单的例子。假设我们有一个 4 位无符号整数。0 将是 0000,1111 将是 15。因此,如果您增加 15 而不是获得 16,您将绕回 0000,因为 16 实际上是 10000,我们不能用少于 5 位来表示它。尔格溢出...
在实践中,数字要大得多,如果 int 是有符号的,它会在溢出时圈出一个很大的负数,但上面基本上是发生了什么。
另一种看待它的方式是将其视为与汽车里程表在达到 999999 公里/英里后再次归零时发生的情况大致相同。
当您将整数存储在内存中时,计算机会将其存储为一系列字节。这些可以表示为一系列 1 和 0。
例如,零将表示为00000000
(8 位整数),通常 127 将表示为01111111
。如果将 1 加到 127,这将“翻转”这些位,并将其交换为10000000
,但在标准的二进制补码表示中,这实际上用于表示 -128。这“溢出”了价值。
对于无符号数,也会发生同样的事情:255 ( 11111111
) 加 1 会变成100000000
,但由于只有 8 个“位”,所以最终会变成00000000
,即 0。
您可以通过对正确的整数大小进行适当的范围检查或使用为您进行适当的异常处理的语言来避免这种情况。
当操作使整数值大于其最大值时,会发生整数溢出错误。
例如,如果您可以拥有的最大值是 100000,而您的当前值是 99999,那么加 2 将使其“溢出”。
您应该关心整数溢出,因为数据可能会在不经意间被更改或丢失,并且可以使用更大的整数类型(参见大多数语言中的 long int)或使用将长数字字符串转换为非常大的整数的方案来避免它们。
溢出是算术运算的结果不适合运算的数据类型。如果添加 255 + 1,则字节大小的无符号整数可能会溢出,因为结果 (256) 不适合字节的 8 位。
如果浮点运算的结果太大而无法在浮点数据类型的指数或尾数中表示,则浮点数可能会溢出。
当浮点运算的结果太小而无法在给定的浮点数据类型中表示时,浮点类型也可能出现下溢。例如,如果浮点数据类型可以处理 -100 到 +100 范围内的指数,并且您将一个值与 -80 的指数平方,结果将有一个大约 -160 的指数,这不适合给定的浮点数据类型。
您需要关注代码中的上溢和下溢,因为它可能是无声的杀手:您的代码会产生不正确的结果,但可能不会发出错误信号。
是否可以安全地忽略溢出在很大程度上取决于程序的性质 - 从 3D 数据渲染屏幕像素对数字错误的容忍度比财务计算要大得多。
溢出检查通常在默认编译器设置中关闭。为什么?因为在每次操作后检查溢出的附加代码需要时间和空间,这会降低代码的运行时性能。
帮自己一个忙,至少在打开溢出检查的情况下开发和测试你的代码。
来自维基百科:
在计算机编程中,当算术运算试图创建一个大于可用存储空间内可以表示的数值时,就会发生整数溢出。例如,将可表示的最大值加 1 构成整数溢出。在这些情况下,最常见的结果是存储结果的最低可表示位(结果被称为回绕)。
您应该关心它,尤其是在为您的程序选择合适的数据类型时,否则您可能会遇到非常微妙的错误。
来自http://www.first.org/conference/2006/papers/seacord-robert-slides.pdf:
当一个整数增加超过它的最大值或减少超过它的最小值时,就会发生整数溢出。溢出可以有符号或无符号。
PS:PDF 详细解释了溢出和其他整数错误情况,以及如何解决/避免它们。
到目前为止,我想与所有其他答案有点相反,它们以某种方式接受蹩脚的破数学作为给定的。这个问题被标记为与语言无关,并且在大量语言中,整数永远不会溢出,所以这是我的讽刺回答:
什么是整数溢出错误?
来自计算黑暗时代的过时神器。
我为什么要关心它?
你没有。
如何避免?
使用整数不会溢出的现代编程语言。(Lisp、Scheme、Smalltalk、Self、Ruby、Newspeak、Ioke、Haskell,任你选……)
我发现在光盘上显示二进制补码表示非常有帮助。
这是 4 位整数的表示形式。最大值为2^3-1 = 7。
对于 32 位整数,我们将看到最大值为2^31-1。
当我们将 1 添加到2^31-1时:顺时针移动一,显然是-2^31,这称为整数溢出
参考:https ://courses.cs.washington.edu/courses/cse351/17wi/sections/03/CSE351-S03-2cfp_17wi.pdf
当您尝试将整数用于高于整数的内部结构由于使用的字节数而可以支持的值时,就会发生这种情况。例如,如果最大整数大小为 2,147,483,647,而您尝试存储 3,000,000,000,则会收到整数溢出错误。