为什么这个递归算法在输入2,147,483,647上给出了错误的答案?

时间:2017-11-05 01:42:25

标签: c++ algorithm recursion

我正在研究以下问题:

  

给定正整数n,您可以执行以下操作:

     
      
  • 如果n为偶数,则用n / 2替换n。
  •   
  • 如果n为奇数,则可以用n + 1或n - 1替换n。
  •   
     

n成为1所需的最小替换次数是多少?

以下是我提出的代码:

#include <fenv.h>

int main() {
    float a = 1.0f;

    fedisableexcept(FE_DIVBYZERO);   // disable div by zero catching

    // generates an inf that **won't be** catched
    float c = a / 0.0f;

    feenableexcept(FE_DIVBYZERO);   // enable div by zero catching

    // generates an inf that **will be** catched
    float d = a / 2.0f;

    return 0
}

当输入为2147483647时,我的代码错误输出33而不是正确的答案,32。为什么我的代码在这里给出了错误的答案?

1 个答案:

答案 0 :(得分:4)

我怀疑这是整数溢出。您列出的数字(2,147,483,647)是可以容纳int的最大可能值,假设您使用的是带符号的32位整数,因此如果您添加一个,则溢出到{{ 1}},即-2,147,483,648。从那里开始,你得到错误的答案就不足为奇了,因为这个价值不是你想要得到的。

计算

时特别发生溢出
INT_MIN

所以你需要修复这种情况来计算(n + 1)/ 2而不会溢出。这是一个非常极端的边缘情况,所以我对代码绊倒它并不感到惊讶。

这样做的一种方法是注意,如果n是奇数,则(n + 1)/ 2等于(n / 2)+ 1(具有整数除法)。所以也许你可以把它重写为

integerReplacement((n+1)/2)

计算相同的值,但没有溢出。