似乎是由特定情况下的整数溢出引起的错误

An error that seems to be caused by an integer overflow for a specific case

我是这个网站的新手。我环顾四周寻找与我相似的问题,但发现 none 所以我自己要问一个新问题。我希望我的格式正确。

我正在编写的程序的一部分总结了一些大数字。这是我目前拥有的代码:

Ball* tmp = player2->RemoveMaxNode();
if (!tmp->GetChosen())
{
    cout << player2->GetHeapType() << " is chosing " << tmp->GetValue() <<  "-" << tmp->GetSumOfDigits() <<endl;
    cout << "Adding " << tmp->GetValue() << " to ";
    cout << player2->GetScore();
    cout << " which should = " << tmp->GetValue() + player2->GetScore() << endl;
    player2->UpdateScore(tmp->GetValue());
    cout << player2->GetHeapType()<< " score now is: ";
    cout << player2->GetScore();
    cout << endl;
    tmp->SetChosen(true);
    numberOfBalls--;
    j++;
    // cout << endl;
}

我的 UpdateScore() 函数是:

void Heap::UpdateScore(unsigned long int value)
{
    this->currentScore += value;
}

这会给我一个输出:

AGENT1 is chosing 937504347-42
Adding 937504347 to 0 which should = 937504347
AGENT1 score now is: 937504347
AGENT1 is chosing 709551656-44
Adding 709551656 to 937504347 which should = 1647056003
AGENT1 score now is: 1647056003
AGENT1 is chosing 681463104-33
Adding 681463104 to 1647056003 which should = 2328519107
AGENT1  score now is: 2328519107
AGENT1 is chosing 672306410-29
Adding 672306410 to 2328519107 which should = 3000825517
AGENT1 score now is: 3000825517
AGENT1 is chosing 667082001-30
Adding 667082001 to 3000825517 which should = 3667907518
AGENT1 score now is: 3667907518
AGENT1 is chosing 378250713-36
Adding 378250713 to 3667907518 which should = 4046158231
AGENT1 score now is: 4046158231
AGENT1 is chosing 309421734-33
Adding 309421734 to 4046158231 which should = 60612669
AGENT1 score now is: 60612669
AGENT1 is chosing 206733105-27
Adding 206733105 to 60612669 which should = 267345774
AGENT1 score now is: 267345774
AGENT1 is chosing 151431905-29
Adding 151431905 to 267345774 which should = 418777679
AGENT1 score now is: 418777679
AGENT1 is chosing 13048925-32
Adding 13048925 to 418777679 which should = 431826604
AGENT1 score now is: 431826604

注意:破折号后的整数值是破折号前的数位之和。这个可以忽略不计。我手动完成并计算了所有这些,它们都是正确的,直到达到

AGENT1 is chosing 309421734-33
Adding 309421734 to 4046158231 which should = 60612669
AGENT1 score now is: 60612669

这个加法的结果应该是 4,355,579,965,但实际上是 60612669。这两个数字的差是 4,294,967,296,我知道这是 2^32 位整数的最大大小。所以我将所有变量都更改为 unsigned long int。 tmp 的值是 unsigned long int,player2 的分数也是。但是,问题仍然存在,我不知道我能做什么。我认为这是一个整数溢出错误,所以我硬编码了所有要相互相加的整数值,结果出现了溢出错误。

main.cpp: In function 'int main(int, char**)':
main.cpp:147:53: warning: integer overflow in expression [-Woverflow]
         unsigned long int asdf = 937504347+709551656+681463104+672306410+667082001+378250713+309421734+206733105+151431905+13048925;
                                  ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~

但我的实际程序并非如此,因为我会收到一个错误,告诉我这是溢出,对吗?我不知道在这里做什么,我已经尝试了我能想到的一切。出了什么问题?

谢谢。

关于这样的陈述:

unsigned long int asdf = 937504347 + 709551656;

int937504347709551656 加在一起创建 int 结果,然后将其加载到 unsigned long 变量。为避免在 int-add 阶段溢出,您应该已经使用了正确的类型,例如:

unsigned long int asdf = 937504347UL + 709551656UL;

你似乎已经知道这一点,因为你得到了编译时错误,因为编译器已经知道你要添加的值。

但是,您的论点是,您会看到编译器在编译时不知道知道的任意值的相同结果,这是不正确的。它只会添加值和翻转无符号值。它也可能会翻转带符号的值,但从技术上讲,这是未定义的行为,所以如果它格式化您的硬盘,请不要感到惊讶:-)


在任何情况下,该标准只保证较高级别的类型具有更大的 或等于 范围到较低级别。一个 unsigned long 需要 是 32 位(更准确地说,有一个可以用 32 位表示的范围)。如果您想要保证大小,请使用 cstdint 中的 uintX_t 类型。 uint64_t 类型应该大大扩展您的范围,为您提供大约 18 quintillion (18,446,744,073,709,551,615) 的最高保证值。