【问题标题】:Finding Prime Number in Java在 Java 中查找素数
【发布时间】:2018-04-26 07:20:19
【问题描述】:

我遇到了一个 Java 程序,它可以判断给定的数字是否是素数。 这是代码。

class FindPrime {
    public static void main(String args[]) {
        int num;
        boolean isPrime;
        num = 14;

        if (num < 2) 
          isPrime = false;
        else 
          isPrime = true;

        for (int i = 2; i <= num / i; i++) {
            if ((num % i) == 0) {
                isPrime = false;
                break;
            }
        }
        if (isPrime) 
          System.out.println("Prime");
        else 
          System.out.println("Not Prime");
    }
}

在这里,我不确定为什么在 for 循环中使用条件 i

【问题讨论】:

标签: java primes


【解决方案1】:

限制条件i &lt;= num / i 是性能优化:

给定例如num = 11i = 3,到目前为止,我们已经检查了 11 是否可以除以 2(否),现在正在移动到 3,我们应该检查它,答案是否定的,它不能被 3 整除。现在我们正在移动到4,我们是否还应该检查11是否可以除以它?这样的除法将产生 2.75,这个值小于我们已经检查过的 3。任何更高的i 都会产生更小的值,我们已经检查过所有这些值,因此进一步检查没有意义。我们现在知道答案了。

【讨论】:

    【解决方案2】:

    别忘了,for loop like for(A;B;C) 表达式 A 在循环开始时计算一次,表达式 B 是从第一个循环开始计算每个循环,表达式 C 从第二个循环开始计算。

    所以最好将偏差从B部分移到A部分。

    i 是性能优化,而且先检查Math.sqrt(num)元素就够了。

    public static boolean isPrime(int val) {
        if (val < 2)
            return false;
    
        for (int i = 2, max = (int)Math.sqrt(val); i <= max; i++)
            if (val % i == 0)
                return false;
    
        return true;
    }
    

    【讨论】:

    • 为了获得更好的性能,您可以检查数字 id 是否除以 2,然后在 for 循环中从 3 开始,并用 +2 增加 i。它会跳过所有偶数,因此素数的计算速度会快两倍。
    【解决方案3】:

    i &lt;= num/i 就像在做i &lt;= sqrt(num)
    如果 num 不是素数,我们可以将其分解为 num = a * b
    如果 num 的一个因子大于 num 的平方根,则另一个必须小于 num 的平方根。
    如果两者都大于它,那么它的乘积将大于 num。

    【讨论】:

    • 非常感谢。
    【解决方案4】:

    这是检查素数与否的更好方法

    package com.practice.competitive.maths;
    
    import java.util.Scanner;
    
    public class CheckPrime {
    
        public static void main(String[] args) {
    
            try(Scanner scanner = new Scanner(System.in)) {
                int testCases = scanner.nextInt();
                long number = scanner.nextLong();
                String result = compute(number);
                System.out.println(result);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        private static String compute(long number) {
            if(number > 0 &&  number % 2 == 0)
                return "No";
            long sqrt = floorSqrt(number);
            for(long i = 3; i<sqrt;i+=2) {
                if(number % i == 0)
                    return "No";
            }
            return "Yes";
        }
    
        private static long floorSqrt(long number) {
            if(number == 0 || number == 1)
                return number;
            long start = 0;
            long end = number;
            long answer = 0;
            while (start <= end) {
                long mid = (start + end)/2;
                if(mid*mid == number)
                    return mid;
                if(mid*mid < number) {
                    start = mid+1;
                    answer = mid;
                }else {
                    end = mid-1;
                }
            }
            return answer;
        }
    
    }
    

    【讨论】:

      【解决方案5】:

      以下解决方案使用Sieve of Sundaram 打印出直到用户提供的数字的所有素数:

      请注意,对于大型输入,您可能会遇到 OutOfMemoryError。

      public static void isPrime(int num) {
          int k = (num - 2) / 2;
          int[] a = new int[k + 1];
          for (int i = 1; i < k + 1; i++) {
              int j = i;
              while ((i + j + 2 * i * j) <= k) {
                  a[i + j + 2 * i * j] = 1;
                  j += 1;
              }
          }
          if (num > 2) {
              System.out.println(2);
          }
      
          for (int l = 1; l < k + 1; l++) {
              if (a[l] == 0) {
                  System.out.println((2 * l + 1));
              }
          }
      }
      

      【讨论】:

        【解决方案6】:

        在程序中添加 for 循环是不明智的,因为它们给你的时间复杂度大于 O(n) 线性时间复杂度,但如果语句是明智的,这里是一个示例

        // code contributed by akoyama koke
        
        public class prime
        {
            public static void main(String[] args) 
            {
                int []arry={1,23,71,3,4,5,6,8,21};
                int n=arry[8];
                if(n%2==0)
                {
                    System.out.print("number is even:"+" "+n);
                }
                else if(n%2!=0)
                {
                    if(n%3!=0 && n%5!=0 && n%7!=0)
                    {
                         System.out.print("number is prime:"+" "+n);
                    }
                    else
                    {
                        System.out.print("number is odd and not prime:"+"  "+n);
                    }
                }
                else
                 System.out.println("number either decimal or a negative not catared for:"+" "+n);
            }
        }    

        【讨论】:

          【解决方案7】:

          是的。 for 循环的中间部分总是被评估,只有当评估给出一个真值时循环内容才会运行。 在您的情况下,循环将在其第一个周期停止,因为 14/2 的模块为 0,因此它将运行将布尔值设置为 false 的 if 主体并退出循环。

          【讨论】:

          • 非常感谢您的解释对我有帮助。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-03-23
          • 2017-01-19
          • 2016-03-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-05-07
          相关资源
          最近更新 更多