【问题标题】:Strange behaviour of integer overflow整数溢出的奇怪行为
【发布时间】:2020-10-21 12:18:13
【问题描述】:

我创建了以下代码来寻找硬币问题的答案。这涉及找到给定 k 面额的硬币的最小数量(其中每个这样的硬币都是无限供应的)以形成目标总和 n。特别是我调查了k=5,面额={2,3,4,5,6}和目标总和n=100的情况。

代码

#include<iostream>
#include<algorithm>
using namespace std;

int coins[5] = {2,3,4,5,6};
int values[101];
int n=100;
int k=5;
int INF = INT_MAX;

int main()
{
    for (int x=1;x<=n;x++)
    {
        values[x] = INF;
        for (int j=1;j<=k;j++)
        {
            if (x-coins[j-1]>=0)
            {
                values[x] = min(values[x],values[x-coins[j-1]]+1);
            }
        }
    }
    cout<<values[100];

    return 0;
}

我收到的此代码的输出是-2147483632。显然一定会发生某种溢出,所以我决定输出INF+1。我得到了INT_MIN 作为答案。但我也记得,在输出一些超出 int 范围的数字时,通常不会出现这样的问题。

我决定输出1e11,令我惊讶的是答案仍然是1e11。为什么会这样,请帮忙。

【问题讨论】:

  • 有符号整数溢出调用未定义行为
  • 有符号整数溢出是未定义的,在实践中它可能仍然有效,这就是你的实验没有帮助解决问题的原因。看起来有效的 UB 仍然是 UB
  • 也许不是你的问题,但你应该设置values[0] = 0;
  • 1e11 的类型为 double,并且是一个可以由 double 完美表示的值。
  • @Damien -- 因为它是在文件范围内定义的,所以 values 中的所有元素都设置为 0。将 values[0] 显式设置为 0 不会改变任何内容。

标签: c++ c++14 integer-overflow


【解决方案1】:

这里:

 values[x] = min(values[x],values[x-coins[j-1]]+1);

例如,对于x=3coins[0]=2,您添加values[1] + 1

但是,values[1] = INT_MAX。然后,在执行此计算时会出现未定义的行为。

您可以通过INF = INT_MAX - 1;解决问题

【讨论】:

    【解决方案2】:

    如果您的程序对有符号整数执行算术运算,产生的结果超出可表示值的范围 - 即,如果此类操作溢出 - 例如 INT_MAX + 1 的情况,则程序的行为是未定义的。

    我决定输出 1e11,令我惊讶的是答案仍然是 1e11。

    1e11 是一个浮点字面量。浮点类型具有与 int 不同的可表示值范围,以及对溢出的不同要求。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-25
      • 2014-05-18
      • 1970-01-01
      • 2012-10-30
      • 2019-11-16
      • 1970-01-01
      • 1970-01-01
      • 2012-02-14
      相关资源
      最近更新 更多