我有这个函数可以生成指定数量的所谓'三角数'。如果我打印出deque后话,数字会增加,跳跃,然后再次增加。随着我的上升,三角形数字永远不会降低,因此必然会发生某种溢出。我尝试通过添加行if(toPush > INT_MAX) return 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;
}
答案 0 :(得分:2)
INT_MAX
是signed int
的最大值。它大约是unsigned int
(UINT_MAX
)最大值的一半。您对toPush
的计算可能远远高于UINT_MAX
,因为您对值进行平方(如果它接近INT_MAX
,则结果将远大于UINT_MAX
toPush
}} 能把持住)。在这种情况下,toPush
包裹并导致比前一个更小的值。
首先,您与INT_MAX
的比较存在缺陷,因为您的类型为unsigned int
,而不是signed int
。其次,即使与UINT_MAX
的比较也是不正确的,因为它意味着toPush
(比较表达式的左操作数)可以保持高于它的最大值 - 这是不可能的。正确的方法是将生成的数字与前一个数字进行比较。如果它更低,你知道你有溢出,你应该停止。
此外,您可能希望使用可以包含更大范围值的类型(例如unsigned long long
)。
答案 1 :(得分:1)
第92682个三角形数字已经大于UINT32_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位变量 生成&amp;存储它们,或者如果需要大量的三角形数字,请使用大数字库。
答案 2 :(得分:0)
在Visual C ++中int
(当然还有unsigned int
)即使在64位计算机上也是32位。
使用unsigned long long
或uint64_t
使用64位值。