我试图理解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中的东西还是编译器或堆栈内存等。
答案 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
可能没有可见的效果,因为b
在a
末尾的噪声中丢失了。两者之间的差异无法正确表示。