c++ - c++ 的除法的其余部分得到“堆栈溢出”异常
问题描述
我试图理解 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 的问题还是编译器或堆栈内存等。
解决方案
resto(2147483647 * 1024, 3);
将递归 2147483647 * 1024 / 3,或约 7330 亿次。每个递归调用都使用少量的自动存储来存储参数和簿记,并且程序可能会在达到一百万次迭代之前耗尽存储空间。
为此,您将不得不使用循环或更智能的逻辑(例如,减去较大的倍数,b
直到使用较小的数字开始有意义),但fmod
可能会更快,更有效。
其他注意事项:
2147483647 * 1024
是一个整数乘以一个整数。如果您的系统是 16 位或 32 位,则此数学运算将在int
s 中发生并溢出。int
当您溢出有符号整数时发生的确切情况是undefined,但通常该数字会进行2s补码环绕(假设 32 位整数为 -1024)。更多关于溢出整数的细节在 C++ 中是否有符号整数溢出仍然是未定义的行为?. 采用
2147483647.0 * 1024
强制浮点数。
还要注意浮点数学是否损坏?浮点数是不精确的,通常很难得到应该与实际相同的浮点数。a == b
当您期望为真时,通常是假的。此外,如果一个数字变得比另一个大太多,则a-b
可能没有明显的效果,因为b
在结尾的噪音中丢失了a
。两者之间的差异无法正确表示。