表示像unsigned int overflow。是什么造成的?

时间:2013-03-08 09:44:15

标签: c++ integer overflow limit

我有这个函数可以生成指定数量的所谓'三角数'。如果我打印出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;
}

3 个答案:

答案 0 :(得分:2)

INT_MAXsigned int的最大值。它大约是unsigned intUINT_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 longuint64_t使用64位值。