C ++递归与大数字查找mod

c++ recursion with big numbers to find mod

本文关键字:数字 查找 mod 递归      更新时间:2023-10-16

嗨,在练习递归时,我发现了一个不使用%运算符来查找模的练习。 所以我写了我的函数,一切正常。 除非我点击 5 位或更多数字的数字,否则此功能会失败。 而且我不确定我是否做错了什么,或者因为电话太多而失败了。 如果电话太多,正常吗?真的可以有太多的函数调用吗?如果将来我有一个真正有用的递归函数,我该如何防止它发生? 因为这对我来说真的没有意义。我做了河内塔递归,无论我想移动多少磁盘,它都没有这个问题。

这是我的函数和前提,两个数字总是正数:

#include <iostream>
using namespace std;
int modulo(int n, int m) {
if (n < m) return n;
else return modulo(n - m, m);
}
int main()
{
int n{ 0 }, m{ 0 };
char check{ 'a' };
do {
cout << "Enter 2 positive integers to calculate their modulo: ";
cin >> n >> m;
if (cin.fail()) {
cerr << "Numbers must be a positive integers. Please try again.n";
cin.clear(); //clear input stream
cin.ignore(std::numeric_limits<std::streamsize>::max(), 'n'); //discard any unprocessed characters
}
else if (n < 0 || m <= 0) {
cerr << "Numbers must be positive and second number cannot be zero.nPlease try again.n";
}
else {
cout << "n%m = " << n << "%" << m << " = " << modulo(n, m) << endl;
cout << " Try again? (enter 'n' to quit): ";
cin >> check;
}
} while (check != 'n');
}

错误是:

在猜测数字.exe中0x00007FF77D5C2793处未处理的异常: 0xC00000FD:堆栈溢出(参数:0x0000000000000001, 0x0000006F322F3F30)。

对于我尝试的数字 40001 % 10,它可以工作,但 44001 % 10 失败 44001 之后的一切对我来说也失败了。我没有尝试过任何其他号码

如果递归太深,则程序耗尽堆栈内存。它被称为堆栈溢出。

int modulo(int n, int m) 
{ 
if (n < m) return n; 
else return modulo(n - m, m); 
}

例如,modulo(1000000, 2)调用modulo(999998, 2),这会调用modulo(999996, 2),依此类推,直到最后modulo(0, 2)堆栈上500001活动modulo函数。在任何合理的系统上,两个整数、返回地址和一个帧指针每次函数调用至少应占用 16 个字节。总共 8 MB 的堆栈空间,通常高于最大堆栈大小。

每个函数调用都必须等待下一个函数的结果,直到它可以完成计算并返回。在返回之前,堆栈必须保存所有变量、参数和返回地址。返回地址是程序中程序在return语句后应恢复的位置。

这些调用会填满堆栈,直到达到其最大限制并且程序崩溃。

在某些情况下,编译器可以将递归转换为循环。在这种情况下,由于递归位于return语句处,因此它可以简单地goto到函数的开头,而无需执行调用。这称为尾调用优化

int modulo(int n, int m) 
{ 
start:
if (n < m) return n; 
else {
n -= m;
goto start;
}
}

如果启用了优化(在 clang 或 G++ 中为 -O2,或在 Visual C++ 上启用发布模式),则不会崩溃,因为编译器将创建一个循环而不是递归。为避免崩溃,只需启用优化即可。

请注意,编译器不需要对此进行优化,也总是可以。这就是为什么不建议有这么深的递归。

您正在递归到深度 4400,这是在自找麻烦。这里也是不必要的,因为您可以使用循环实现相同的算法:

while (n >= m) n -= m ;
return n ;