就像unsigned int overflow.是什么引起的?

Acting like unsigned int overflow. What is causing it?

本文关键字:是什么 unsigned int overflow 就像      更新时间:2023-10-16

我有这个函数,它生成一个指定数量的所谓的'三角形数'。如果我输出deque后记,数字增加,跳下来,然后再次增加。三角形数永远不会随着i的增加而降低,所以一定会发生某种溢出。我试图通过添加行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;
}

INT_MAXsigned int的最大值。约为unsigned int (UINT_MAX)最大值的一半。你对toPush的计算可能会比UINT_MAX高得多,因为你对这个值进行了平方(如果它接近INT_MAX,那么结果将比toPush所能容纳的UINT_MAX大得多)。在这种情况下,toPush环绕,结果值比前一个小。

首先,你与INT_MAX的比较是有缺陷的,因为你的类型是unsigned int,而不是signed int。其次,即使与UINT_MAX进行比较也是不正确的,因为它意味着toPush(比较表达式的左操作数)可以保存高于其最大值的值-这是不可能的。正确的方法是将生成的数字与之前的数字进行比较。如果它较低,你知道你有溢出,应该停止。

此外,您可能希望使用可以容纳更大范围值的类型(例如unsigned long long)。

第92682个三角形数已经大于UINT32_MAX。但这里的罪魁祸首要早得多,在i * (i + 1)的计算中。在这里,对于65536个三角形数,计算会溢出。如果我们询问具有原生bignum支持的Python:

>>> 2**16 * (2**16+1) > 0xffffffff
True

哦。然后,如果您检查存储的数字,您将看到您的序列回落到低值。为了尝试在Python中模仿标准中对这种情况的行为的描述:

>>> (int(2**16 * (2**16+1)) % 0xffffffff) >> 1
32768

,这是您将看到的65536个三角数的值,这是不正确的。

这里检测溢出的一种方法是确保生成的数字序列是单调的;即,如果生成的第n个三角形数严格大于第(N-1)个三角形数

为了避免溢出,可以使用64位变量生成&存储它们,或者如果你需要大量的三角形数,使用一个大的数字库。

在visualc++中,int(当然还有unsigned int)即使在64位计算机上也是32位的。

使用unsigned long longuint64_t来使用64位值