[英]Java: Find out if a number is prime recursively
我正在编写一个函数,如果数字是素数则返回真,否则返回假
这是我当前的代码:
public static boolean checkPrime(int n, int currDivisor){
if(n < 2){
return true;
}
if(currDivisor == (n/2)){
return true;
}
else if(n % currDivisor == 0 ){
return false;
}
else{
return checkPrime(n, currDivisor + 1);
}
}
public static void main(String[] args){
System.out.println(checkPrime(23352, 2));
}
它适用于许多测试用例,除了像“1000000007”这样的数字,在那里我遇到内存不足错误。 我如何调整此代码以提高空间效率?
根本问题是递归不是正确的方法。 原始性测试不是一个递归问题,对于大量用户,您将始终很快超过可用存储。 我建议您在网络上进行有关“原始性测试”的研究。
关于确定问题是否递归的经验法则,我已经做了很久了,我不确定我能否表达出已经完全直观的内容,所以我会让别人去做。
但是,值得指出的是,一些数学上递归的问题具有计算解决方案,其中迭代远比幼稚的递归好得多。 素数(哈!)的例子是斐波那契数。 对于较大的n,天真的递归解决方案会占用内存并执行冗余计算,而迭代解决方案在整个过程中都更快,更好。
我看到的第一个问题是您的程序是越野车。 似乎认为0、1,&4是质数,而3不是。 我看到的第二个问题是,它浪费了堆栈帧,在递归之前没有正确处理简单的情况。 这是我对您的代码的重做:
public static boolean checkPrime(int n) {
return checkPrime1(n, 3);
}
public static boolean checkPrime1(int n, int currDivisor) {
if (n < 2) {
return false;
}
if (n % 2 == 0) {
return (n == 2);
}
if (currDivisor * currDivisor > n) {
return true;
}
if (n % currDivisor == 0) {
return false;
}
return checkPrime1(n, currDivisor + 2);
}
至于处理:
System.out.println(checkPrime(1000000007));
您仍然会遇到java.lang.StackOverflowError
但这还不是故事的结尾。 大多数语言都会决定要分配给特定用途的内存量。 像Perl这样的稀有语言会将内存重新分配给最需要它的资源,而不会对程序的行为做任何假设。
您可以更改分配给Java堆栈的内存量-使用-Xss2m
参数调用java
分配足够的额外堆栈,以供您测试1000000007(顺便说一下,是true
)。
如果你改变了三种int
上述报关单long
,你就可以像测试数字2547487897L
只要您展开堆栈或更大( -Xss4m
在这种情况下)。
我并不是说这是递归的好问题,不是。 但是,如果您要使用递归,请明智地使用它。 不好的递归使递归变得不好用。 有低效的递归Fibonnaci算法(通常是双递归)和高效的(单递归)算法。 递归代码通常最适合递归数据。
某些语言(不是Java一致的语言)可以将上述代码作为尾部递归进行优化,并使其具有有效的迭代性能。
/*by mostafa asem aljbali*/
static boolean isPrime(int num, int i){
if (num <= 2){
return (num == 2) ? true : false;
}
if (num % i == 0){
return false;
}
if (i * i > num){
return true;
}
return isPrime(num , (i + 1));
}
public static void main(String[] args){
System.out.println("Is Prime: "+ isPrime(7, 2));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.