C ++的除法运算的剩余部分得到“堆栈溢出”异常

时间:2019-03-31 00:38:49

标签: c++ visual-studio-2017 stack-overflow

我试图理解C ++中的一些概念,并编写了这段代码来获取除法的其余部分(例如%运算符):

double resto(double a, double b) {
    if (a == b) return 0;
    else if (a < b) return a;
    else {
        return resto(a-b, b);
    }
}

当我以较低的数字(例如(12,3)或(2,3))运行它时,它运行良好。 但是,如果我尝试使用参数(2147483647 * 1024,3)运行它,则会得到:

Stack overflow (parameters: 0x0000000000000001, 0x000000F404403F20)

由于我是C ++的新手,所以我不确定是Visual Studio 2017中的东西还是编译器或堆栈内存等。

1 个答案:

答案 0 :(得分:3)

resto(2147483647 * 1024, 3); 

将要递归2147483647 * 1024/3,约合7,330亿次。每个递归调用都会使用少量的自动存储空间来存储参数和簿记,并且该程序在达到一百万次迭代之前可能会耗尽存储空间。

为此,您将不得不使用循环或更智能的逻辑(例如,减去b的较大倍数,直到使用较小的数字才有意义),但是fmod可能会更快并且更更有效。

其他说明:

2147483647 * 1024

是整数乘以整数。如果int是系统上的16或32位,则该数学运算将在int内执行并溢出。确实,当您使有符号整数溢出时会发生undefined,但通常该数字会进行2s compliment环绕(假设32位整数,则为-1024)。 Is signed integer overflow still undefined behavior in C++?中有关溢出整数的更多详细信息。使用

2147483647.0 * 1024

强制使用浮点数。

还要注意Is floating point math broken?浮点数不够精确,通常很难获得应该相同且实际上相同的浮点数。当您期望为真时,a == b通常为假。另外,如果一个数字比另一个数字大得多,则a-b可能没有可见的效果,因为ba末尾的噪声中丢失了。两者之间的差异无法正确表示。