C++ 就像无符号整数溢出一样。是什么原因造成的?
我有一个函数,它生成一个指定数量的所谓“三角形数”。如果我打印出deque的后记,数字会增加,跳下,然后再增加。当我上升时,三角形的数字永远不会变低,所以一定有某种溢出发生。我试图通过添加行C++ 就像无符号整数溢出一样。是什么原因造成的?,c++,integer,overflow,limit,C++,Integer,Overflow,Limit,我有一个函数,它生成一个指定数量的所谓“三角形数”。如果我打印出deque的后记,数字会增加,跳下,然后再增加。当我上升时,三角形的数字永远不会变低,所以一定有某种溢出发生。我试图通过添加行if(toPush>INT_MAX)返回I-1来修复它尝试在结果溢出时停止函数生成更多数字(并返回它生成的数字)。这不起作用,但是,输出仍然不正确(增加一段时间,跳到一个较低的数字,然后再次增加)。我加的那句话实际上似乎什么都没做。未联系到返回。有人知道这里发生了什么吗 #include <iostre
if(toPush>INT_MAX)返回I-1来修复它
尝试在结果溢出时停止函数生成更多数字(并返回它生成的数字)。这不起作用,但是,输出仍然不正确(增加一段时间,跳到一个较低的数字,然后再次增加)。我加的那句话实际上似乎什么都没做。未联系到返回。有人知道这里发生了什么吗
#include <iostream>
#include <deque>
#include <climits>
int generateTriangleNumbers(std::deque<unsigned int> &triangleNumbers, unsigned int generateCount) {
for(unsigned int i = 1; i <= generateCount; i++) {
unsigned int toPush = (i * (i + 1)) / 2;
if(toPush > INT_MAX) return i - 1;
triangleNumbers.push_back(toPush);
}
return generateCount;
}
#包括
#包括
#包括
int-generateTriangleNumber(std::deque&triangleNumber,无符号int-generateCount){
for(unsigned int i=1;i int_MAX)返回i-1;
三角形编号。向后推(顶推);
}
返回生成计数;
}
在Visual C++中,代码> int (当然,<代码>未签名INT/COM>)是64位计算机上的32位。
使用无符号long-long
或uint64\u t
使用64位值。第92682个三角形数已经大于UINT32\u MAX
。但是这里的罪魁祸首要早得多,在计算i*(i+1)
时。在这里,65536三角形数的计算溢出。如果我们询问Python的本机bignum支持:
>>> 2**16 * (2**16+1) > 0xffffffff
True
哎呀。然后,如果你检查你存储的数字,你会看到你的序列下降回低值。要尝试模仿标准对本例行为的描述,请使用Python:
>>> (int(2**16 * (2**16+1)) % 0xffffffff) >> 1
32768
这就是你将看到的65536三角形数字的值,这是不正确的
检测溢出的一种方法是确保生成的数字序列是单调的;即,如果生成的第N个三角形编号严格大于第(N-1)个三角形编号
为了避免溢出,您可以使用64位变量来生成和存储这两个变量,或者如果需要大量的三角形数,可以使用一个大的数字库。INT\u MAX
是有符号INT
的最大值。它大约是unsigned int
(UINT\u MAX
)最大值的一半。您对toPush
的计算可能会比UINT\u MAX
高得多,因为您将该值平方(如果该值接近INT\u MAX
,则结果将比toPush
所能容纳的UINT\u MAX
大得多)。在这种情况下,toPush
环绕并产生比前一个更小的值
首先,您与INT\u MAX
的比较是有缺陷的,因为您的类型是unsigned INT
,而不是signed INT
。其次,即使是与UINT_MAX
的比较也不正确,因为这意味着toPush
(比较表达式的左操作数)可以保持高于其最大值的值,而这是不可能的。正确的方法是将生成的数字与上一个数字进行比较。如果水位较低,你就知道你已经溢油了,你应该停下来
此外,您可能希望使用能够容纳更大范围值的类型(例如无符号long-long
)。i的第一个值对什么不起作用?如果你用手进行特定的计算,你会观察到什么?你如何期望任何数字严格地大于最大可能的数字?你应该检查计算的各个步骤。具体来说,如果溢出发生在(i*(i+1))
中,您以后将无法检测到它。@Mat我认为作为一项测试,我将检查它是否大于INT_MAX,但仍然使用无符号INT。这样,希望它能在数字增长到可能大于无符号INT的大小之前找出问题。@OliCharlesworth我将尝试找出它的值这工作做得很好。我没有想到简单地检查新的数字是否大于上一个数字。我更改了密码,现在正是时候退出。