【问题标题】:detecting 32 bit integer overflow检测 32 位整数溢出
【发布时间】:2017-07-29 12:35:54
【问题描述】:

我有一个简单的方法,基本上可以反转有符号整数。此函数一直有效,直到整数小于或等于 32 位。 例如:-

input = 321
output = 123

input = -321
output = -123

input = 1534236469
output = 9646324351    //this value is wrong. 

expected output = 0

我想检测整数溢出并在这种情况下返回 0。 下面是函数的代码

    int reverse(int x) {
    int number = x;
    bool negative = false;
    if(number<0){
        negative = true;
        number *= -1;
    }

    int reversed = 0;
    while (number != 0){
        int reminder = number % 10;
        reversed = (reversed * 10) + reminder;
        number /= 10;
    }
    if(negative){
        reversed *= -1;
    }
    return reversed;
}

此外,如果我将输入和输出更改为有符号长整数,我会得到所需的输出,但我想检测整数溢出并返回 0。

【问题讨论】:

  • 当您使用调试器逐步执行您的算法时,一次一行,并在每一步检查所有变量的值,您做了什么观察?您的问题的答案是:学习如何使用调试器。了解如何使用调试器是每个 C++ 开发人员必备的技能。
  • @SamVarshavchik:不,答案不是那样。他想检测何时发生溢出。他需要一个可以做到的算法。
  • @SamVarshavchik,谢谢。我通过调试器进行了检查。溢出发生在乘法中。了解是否有一种简单的方法可以检测到在算术运算的情况下数字可能会溢出。
  • 乘法前需要检查reversed。如果它大于 INT_MAX/10,那么它将溢出。也许您还需要其他检查。
  • 代码的工作假设值被反转并且反转的值都可以用 32 位整数类型表示。 “错误”的值不能以 32 位类型表示。您需要在乘以 10 之前和添加“提醒”之前检查潜在的溢出。

标签: c++ algorithm


【解决方案1】:

在将 reversed 乘以 10 之前,只需检查以确保它足够小,可以乘以 10。

同样,在添加 remainder 之前,请检查以确保它足够小以添加 remainder

你可以使用一个聪明的技巧来进行加法,但在你的水平上你可能不应该:

if ((reversed += remainder) < remainder) {
    //overflow
}

请注意,该技巧仅在 reversedremainder 均未签名时才有效。

【讨论】:

  • 这只有在reversed 是一个无符号变量时才能保证有效,你应该提及它。
  • 还是不行。它必须是未签名的。有符号溢出就是UB,不管是正溢出还是负溢出。
  • @geza,这是真的,我讨厌它。
【解决方案2】:

此提示可能会帮助您完成作业:

如果你的最终数字是 10 位长并且第一个数字最终大于或等于 2,你只会得到整数溢出。

这意味着如果您的原始数字也是 10 位长并且最后一位是 2 或以上,您将获得整数溢出。

【讨论】:

    猜你喜欢
    • 2014-02-09
    • 1970-01-01
    • 2016-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-22
    • 1970-01-01
    相关资源
    最近更新 更多