【问题标题】:Java Prime finder efficiencyJava Prime 查找器效率
【发布时间】:2016-03-05 10:08:32
【问题描述】:

我想将所有小于 10 的素数相加。

这是我的代码:

    boolean kontroll = true;
    long limit = 10;
    long checker = 2;
    long sum = 0;

    while (checker < 10) {
        for (long i = 3; i < Math.sqrt(checker); i += 2) {
            if (checker % 2 == 0) {
                kontroll = false;
                break;
            } else {
                if (checker % i == 0) {
                    kontroll = false;
                } 
            }
        } if (kontroll) {
            sum += checker; 
            System.out.println("Prim: " + checker);
        }
        checker++;
        kontroll = true;
    }
    System.out.println(sum);

我得到这个输出:

Prim: 2
Prim: 3
Prim: 4
Prim: 5
Prim: 6
Prim: 7
Prim: 8
Prim: 9
44

这个版本有什么问题?如果我删除 Math.sqrt(checker); 程序可以工作,但速度很慢。我不能取检查器的平方根吗?

【问题讨论】:

  • 在 while 语句之前分配一个 float q = Math.sqrt(checker);,然后有 for(long i=2 ; i 代替。这应该会加快您的代码速度。
  • @ArifBurhan 你为什么使用float
  • @Aminorph:您的程序没有正确识别素数,因此总和也不正确。我认为部分原因是您在 while 循环的末尾和下一次迭代中设置了“kontroll = true”,如果 for 循环甚至没有执行一次,那么下一个数字将始终用于计算总和跨度>
  • @MikeCAT double 也同样有效,但这里不需要高精度,因为您要与 long 进行比较。
  • @ArifBurhan 使用float 给了我compile error。您正在与long 进行比较,那么为什么不与long 进行比较呢?

标签: java performance square-root


【解决方案1】:

checker 为非负数且小于等于8 时,3 大于Math.sqrt(checker)

试试这个:

boolean kontroll = true;
long limit = 10;
long checker = 2;
long sum = 0;

while (checker < 10) {
    if (checker != 2 && checker % 2 == 0) { // move this check out of the loop and correct condition
        kontroll = false;
    } else {
        long max = (long)Math.sqrt(checker);
        for (long i = 3; i <= max; i += 2) { // change < to <=
            if (checker % i == 0) {
                kontroll = false;
                break; // add break for better performance
            } 
        }
    }
    if (kontroll) {
        sum += checker; 
        System.out.println("Prim: " + checker);
    }
    checker++;
    kontroll = true;
}
System.out.println(sum);

【讨论】:

  • 您可以改进if (checker... 以阅读if (checker % 2 == 0) { kontroll = checker == 2; } else { ... }
【解决方案2】:

您的kontroll 变量分配有true,并且您从3 循环到sqrt(checker),在您的情况下checker 将低于10

所以,你的代码只会进入你的循环一次,当checker = 10 (3 &lt; sqrt(10)) 和其他时间,他们只是通过到

if (kontroll) { //remember, your kontroll assigned to true =)
    sum += checker; 
    System.out.println("Prim: " + checker);
} 

并且总和将始终相加。干杯!

【讨论】:

    【解决方案3】:

    一个优化的版本,可以打印到某个数字的素数。

    final List<Integer> primes = new ArrayList<>(Collections.singletonList(2));
    
    /**
     * Print prime numbers up to {@code n} inclusive
     */
    public void findPrimes(int n) {
        // check only odd numbers
        for (int i = 3; i <= n; i += 2) {
            isPrime(i);
        }
        System.out.println(primes);
    }
    
    // a function which does have side effects (adds to the primes collection)
    private boolean isPrime(final int i) {
        // we really need to check for divisors only up to sqrt
        int sqrt = (int)Math.sqrt(i);
        // and we really need to find only prime divisors since any
        // number can be written as a product of prime numbers
        for (int prime : primes) {
            if (i % prime == 0) {
                return false;
            }
            if (prime > sqrt) {
                break;
            }
        }
        primes.add(i);
        return true;
    }
    

    【讨论】:

    • 不错!谢谢!
    猜你喜欢
    • 2014-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-11
    • 2018-04-15
    • 2010-10-28
    • 1970-01-01
    相关资源
    最近更新 更多