【问题标题】:How to determine if a number is prime如何判断一个数是否为素数
【发布时间】:2017-03-05 02:39:12
【问题描述】:

好吧,我的问题不是如何判断一个数字是否是素数,因为我想我已经弄清楚了,而是如何让它正确显示。

这是我的代码:

public static void main(String[] args) {
    // Declare Variables
    int randomNumbers = 0;
    int sum = 0;
    //Loop for number generation and print out numbers
    System.out.print("The five random numbers are: ");
    for (int i = 0; i <= 4; i++)
    {
        randomNumbers = (int)(Math.random()*20);
        sum += randomNumbers;

        if (i == 4) {
            System.out.println("and " + randomNumbers + ".");
        }
        else {
            System.out.print(randomNumbers + ", ");
        }
    }
    //Display Sum
    System.out.println("\nThe sum of these five numbers is " + sum + ".\n");

    //Determine if the sum is prime and display results
    for(int p = 2; p < sum; p++) {
        if(sum % p == 0)
            System.out.println("The sum is not a prime number.");
        else 
            System.out.println("The sum is a prime number.");
        break;
        }
    }


}

现在我的问题是,如果数字最终是 9,它会说它是质数,但它不是。我认为问题在于 break 在一个循环后停止它,所以它不会增加变量 p 所以它只是测试除以 2(我认为)。但是,如果我删除断点,它将在每次传递时打印出“总和是/不是素数”,直到它退出循环。不知道在这里做什么。

【问题讨论】:

    标签: java eclipse loops primes


    【解决方案1】:

    您确定数字是否为素数的方法是正确的方法。 为了使它不会始终打印出该数字是否为素数,您可以有一个外部变量,它表示该数字是否为素数。

        boolean prime = true;
        for (int p = 2; p < sum; p++) {
            if (sum % p == 0) {
                prime = false;
                break;
            }
        }
        if (prime)
            System.out.println("The sum is a prime number.");
        else
            System.out.println("The sum is not a prime number.");
    

    通过这种方法,程序会假设这个数是素数,直到证明它是错误的。因此,当它发现它不是素数时,它会将变量设置为 false 并跳出循环。

    然后在循环结束后,您只需打印该数字是否为素数。

    使这个循环更快的一种方法是从 p = 2 到 p = sum 的平方根。所以使用这种方法,你的 for 循环将如下所示:

        double sq = Math.sqrt((double)sum);
        for (int p = 2; p < sq; p++) {
            //Rest of code goes here
        }
    

    希望对你有帮助

    【讨论】:

    • 非常有帮助,虽然你离开了休息;在那里,这让我很困惑,直到我意识到我需要摆脱它。非常感谢您的帮助!
    • 第一次找到一个因子时就退出循环,因为它不需要再寻找了。
    • 你的逻辑是正确的,但它没有优化。因此,仅将 for 循环迭代到数字的平方根而不是数字。并将for 循环变量(从 3 开始)增加 2 而不是 1。我已经发布了答案,请参阅该答案以获取更多详细信息。
    • 最后一个for循环应该包含范围上限,像这样 for (int p = 2; p
    • 1 不是素数。一个大于 1 的整数称为素数,如果它的唯一正除数(因数)是 1 和它本身。
    【解决方案2】:

    您需要将数字是否为素数存储在循环外的布尔值中:

    //Determine if the sum is prime and display results
    boolean isPrime = true;
    for(int p = 2; p < sum; p++) {
        if(sum % p == 0){
            isPrime = false;
            break;
        }
    }
    if(isPrime){
       System.out.println("The sum is a prime number.");
    } else {
       System.out.println("The sum is not a prime number."); 
    }
    

    【讨论】:

    • 你的逻辑是正确的,但它没有优化。因此,仅将 for 循环迭代到 number 的平方根而不是 up to number。并将 for 循环变量(从 3 开始)增加 2 而不是 1。我已经发布了答案,请参阅该答案以获取更多详细信息。
    【解决方案3】:

    您是对的,目前您的代码测试除以二,并且 break 命令在一个循环后停止。

    在您的循环第一次执行 (p==2) 之后,break 将始终停止循环。

    对代码的最快修复将像这样更改循环部分:

    boolean isPrime=true;
    for(int p = 2; p < sum; p++) {
        if(sum % p == 0) {
            isPrime=false;
            System.out.println("The sum is not a prime number.");
            break;
        }
    }
    if (isPrime)
        System.out.println("The sum is a prime number."); 
    

    可以改进此代码以提高效率和代码优雅性。

    为了提高效率,您不需要检查所有小于 sum 的数字的整除性,检查所有小于 sum 的平方根的数字就足够了。

    为了更好的代码,创建一个单独的函数来测试一个数字是否是素数。

    这是一个实现两者的示例。

     // tests if n is prime
     public static boolean isPrime(int n) {
         if (n<2) return false;
         for(int p = 2; p < Math.sqrt(n); p++) {
            if(n % p == 0) return false;  // enough to find one devisor to show n is not a prime
         }
         return true; // no factors smaller than sqrt(n) were found
     }
    
     public static void main(String []args){
        ...
        System.out.println("sum is "+ sum);
        if (isPrime(sum)) 
            System.out.println("The sum is a prime number.");
        else 
            System.out.println("The sum is not a prime number.");
     }
    

    【讨论】:

    • 您在 for 循环括号中提到了 Math.sqrt(n),这是一种不好的做法。一次又一次地计算平方根会降低性能。最好将数字的平方根存储在临时变量中并在 for 循环中使用。
    • 将 for 循环变量(从 3 开始)增加 2 而不是 1。我已经发布了答案,请参阅该答案以获取更多详细信息。
    【解决方案4】:

    到目前为止,已经发布了很多正确的答案,但没有一个是优化的。这就是为什么我想在这里与您分享确定素数的优化代码。请看下面的代码 sn-p...

    private static boolean isPrime(int iNum) {
    boolean bResult = true;
    if (iNum <= 1 || iNum != 2 && iNum % 2 == 0) {
        bResult = false;
    } else {
        int iSqrt = (int) Math.sqrt(iNum);
        for (int i = 3; i < iSqrt; i += 2) {
        if (iNum % i == 0) {
            bResult = false;
            break;
        }
        }
    }
    return bResult;
    }
    

    以上代码的好处-:

    1. 它也适用于负数以及 0 和 1。
    2. 它只会对奇数运行 for 循环。
    3. 它将 for 循环变量增加 2 而不是 1。
    4. 它只会将for 循环迭代到数字的平方根而不是数字。

    解释-:

    以上四点我都提到了,我会一一解释。必须针对无效输入而不是仅针对有效输入编写适当的代码。到目前为止所写的任何答案都仅限于数字iNum &gt;=2 的有效输入范围。

    我们应该知道只有奇数可以是素数注意-:2是唯一的偶素数。所以我们必须偶数不运行for循环。

    我们不能为它的变量i 的偶数值运行for 循环,因为我们知道只有偶数可以除以偶数。我在上面已经提到,只有奇数可以是素数,除了 2 是偶数。 因此无需在 for 循环内运行代码,以获取 for 中变量 i 的偶数值

    我们应该只迭代 for 循环到数字的 平方根 而不是数字。很少有答案实现了这一点,但我还是想在这里提一下。

    【讨论】:

      【解决方案5】:

      小素数

      使用Apache Commons Math 素数检验,方法与int范围内的素数有关。您可以在GitHub 上找到源代码。

      <dependency>
          <groupId>org.apache.commons</groupId>
          <artifactId>commons-math3</artifactId>
          <version>3.6.1</version>
      </dependency>
      
      // org.apache.commons.math3.primes.Primes
      Primes.isPrime(2147483629);
      

      它使用 Miller-Rabin 概率检验的方式是 结果是有保证的:它使用第一个素数作为连续的 基础(参见Menezes, table 4.1 的应用密码学手册/第 140 页)。

      大素数

      如果您正在寻找大于Integer.MAX_VALUE 的素数:

      1. 使用BigInteger#isProbablePrime(int certainty)预验证prime候选

        如果这个 BigInteger 可能是素数,则返回 true,如果是,则返回 false 肯定是复合的。如果确定性 ≤ 0,则返回 true。 参数:确定性 - 调用者不确定性的度量 愿意容忍:如果调用返回 true 的概率 这个 BigInteger 是素数超过 (1 - 1/2certainty)。执行 该方法的时间与该参数的值成正比。

      2. 接下来使用"AKS Primality Test" 来检查候选人是否确实是素数。

      【讨论】:

        【解决方案6】:

        具有最有效的时间复杂度,即 O(sqrt(n)):

        public static boolean isPrime(int num) {
        
            for (int i = 2; i * i <= num; i++) {
                if (num % i == 0) {
                    return false;
                }
            }
        
            return true;
        }
        

        【讨论】:

          猜你喜欢
          • 2011-05-24
          • 2010-12-05
          • 2015-02-08
          • 2020-02-14
          • 2016-01-25
          • 2016-02-10
          • 2018-01-16
          相关资源
          最近更新 更多