Java 我的语法有什么问题吗?我这样做是否有效?

Java 我的语法有什么问题吗?我这样做是否有效?,java,syntax,methods,Java,Syntax,Methods,我正在尝试一种方法,它能告诉我天气好坏,一个数是素数是真是假。代码如下: class prime { public static boolean prime (int a, int b) { if (a == 0) { return false; } else if (a%(b-1) == 0) { return false;

我正在尝试一种方法,它能告诉我天气好坏,一个数是素数是真是假。代码如下:

class prime
{

    public static boolean prime (int a, int b) 
    { 
        if (a == 0) 
        {
            return false; 
        }
        else if (a%(b-1) == 0) 
        {
            return false; 
        }
        else if (b>1) 
        {
            prime (a, b-1) ;
        }
        else
        {
            return true; 
        }

    }

    public static void main (String[] arg) 
    {
        System.out.println (prime (45, 45)) ; 
    }
}
当我尝试编译此文件时,会收到以下错误消息:

prime.java:23: missing return statement
    }
    ^
1 error
我可能误解了错误消息所说的内容,但在我看来,并没有缺少返回语句,因为对于每一组可能的条件,我都有一个返回语句。如果a为0,则返回false;如果不是,则检查a是否可除以b;如果是,则返回;如果不是,则返回;如果b大于1,则重新开始。如果b不大于1,它也会返回

  • 而且,不得不这样做似乎有点混乱 使此方法取两个整数 都是相同的int

  • 我的语法有什么问题/为什么会收到错误消息?有没有办法让我在main中使用的方法只需要取一个int(也许另一个方法会将该int分割成两个克隆,然后传递给
    公共静态布尔素数
    property)

  • 还是有更有效的解决方法 这是我错过的 完全


如果
b
大于
1
,则函数不会返回任何内容


可能是
返回素数(a,b-1);

您似乎有这样一种印象,因为递归最终会找到一个会命中return语句的基本情况,那么该返回将在所有递归调用中冒泡出来。这不是真的。每个递归调用都必须像下面这样传递结果:

return prime(a, b - 1);

为了提高效率,更多地考虑你的条件。你真的需要测试从2到N的每一个因子吗?是否有一个不同的停止点可以帮助质数测试更快地完成

为了制作一个更好的API,考虑将递归方法私有化,用一个公共入口点帮助引导过程。

public static boolean prime(int n) {
  return recurse(n, n);
}

private static boolean recurse(int a, int b) {
 ...
}
将一个方法设置为private意味着不能从另一个类调用它。该类的用户实际上看不到它。这里的目的是通过提供一个public helper方法来隐藏“丑陋”的额外参数


想想一些复合数的因子。10因子到5×2。12因子到6×2。14因子到7×2。现在想想25.25因子到5×5。9呢?你看到一个模式了吗?顺便说一下,如果这不是家庭作业,请让我知道。这对我来说很难。在你的
素数
函数中,有四种可能的code路径,其中一个路径不返回任何内容。这就是错误消息所抱怨的。您需要替换:

prime (a, b-1) ;
与:

else if(b>1)
情况下

话虽如此,这实际上不是计算一个数是否为素数的好方法。问题是,每个递归调用都分配一个堆栈帧,如果您试图确定9999999是否为素数,您将遇到严重的堆栈溢出问题

递归对于某些问题的子集来说是一个非常好的工具,但是你需要知道堆栈的深度。至于更有效的解决方案,你可以进行很多测试来确定一个数字不是素数,然后用蛮力测试来检查其他数

你应该注意的一件事是首先检查较小数字的可分性,因为这会更快地缩小搜索范围。并且不要在乘法可以完成的地方使用除法,乘法通常更快(尽管并不总是如此)

还有一些可能是鬼鬼祟祟的把戏:

  • 除2以外,以2、4、6、8或0结尾的每个数字都是非素数
  • 除5以外,以5结尾的每一个数字都是非素数。 仅这两条规则就可以减少60%的搜索空间。假设您以字符串形式获取测试编号,那么即使在转换为整数类型之前,也可以测试该字符串的最后一位数字
对于整除性检查,有一些更复杂的规则。如果你取9的倍数,将所有数字相加,得到一个新的数字,然后再对该数字进行一次运算,直到得到一个数字,你会发现它总是9

这将使您的搜索空间再减少10%,尽管需要花费更多的时间进行检查。请记住,这些检查只对非常大的数字有利。对于32位整数来说,优势并不是很大,因为预先计算的位图在那里会更有效(见下文)

对于一个简单的开始,我将使用以下迭代解决方案:

public static boolean prime (int num) {
    int t = 2;
    while (t * t <= num) {
        if ((num % t) == 0) {
            return false;
        }
        t++;
    }
    return true;
}

递归方法必须返回一个值才能展开

    public static boolean prime (int a, int b) 
{
    if (a == 0) 
    {
        return false; 
    }
    else if (a%(b-1) == 0) 
    {
        return false; 
    }
    else if (b>1) 
    {
        return prime (a, b-1) ;
    }
    else
    {
        return true; 
    }

}

我可能会用另一种方式编写,但这就是您无法编译代码的原因。

为了回答为什么7不起作用,请假设您是计算机,并通过您的逻辑进行操作。以下是您编写的内容

class prime
{

    public static boolean prime (int a, int b) 
    { 
        if (a == 0) 
        {
            return false; 
        }
        else if (a%(b-1) == 0) 
        {
            return false; 
        }
        else if (b>1) 
        {
            // Have to add the return statement
            // here as others have pointed out!
            return prime(a, b-1);
        }
        else
        {
            return true; 
        }

    }

    public static void main (String[] arg) 
    {
        System.out.println (prime (45, 45)) ; 
    }
}
让我们从7开始

if(7 == 0) // not true, don't enter this block
else if(7 % 6 == 0) // not true
else if(7 > 1) // true, call prime(7, 6)

if(7 == 0) // not true, don't enter this block
else if(7 % 5 == 0) // not true
else if(6 > 1) // true, call prime(7, 5)

if(7 == 0) // not true, don't enter this block
else if(7 % 4 == 0) // not true
else if(5 > 1) // true, call prime(7, 4)
…继续向下调用prime(7,2)

否则如果(7%1==0)为true,则返回false


当你开始调用
prime(n,2)
时,它总是返回false,因为你有一个逻辑错误。

我认为原来的问题已经得到了回答-你需要在
的主体中插入
return
,否则如果(b>1)
-我只是想指出,当b的值为1时,您的代码仍然会崩溃,抛出一个
算术异常
,因为
a%(b-1)
将被计算为
a%0
,导致被零除

如果(a==0 | | b==1){}

这不会改善程序查找素数的方式,只是确保少了一种方法使其崩溃。

与@paxdiblo的答案类似,但效率略高

public static boolean isPrime(int num) {
    if (num <= 1 || (num & 1) == 0) return false;
    for (int t = 3; t * t <= num; t += 2)
        if (num % t == 0)
            return false;
    return true;
}
public静态布尔值isPrime(int num){

如果(num),即必须使用
返回素数(a,b-1);
而不仅仅是
素数(a,b-1);
但如果b>1,则它将
if(7 == 0) // not true, don't enter this block
else if(7 % 6 == 0) // not true
else if(7 > 1) // true, call prime(7, 6)

if(7 == 0) // not true, don't enter this block
else if(7 % 5 == 0) // not true
else if(6 > 1) // true, call prime(7, 5)

if(7 == 0) // not true, don't enter this block
else if(7 % 4 == 0) // not true
else if(5 > 1) // true, call prime(7, 4)
if(7 == 0) // not true, don't enter this block
public static boolean isPrime(int num) {
    if (num <= 1 || (num & 1) == 0) return false;
    for (int t = 3; t * t <= num; t += 2)
        if (num % t == 0)
            return false;
    return true;
}