You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Project Euler第87题代码结果错误,寻求问题定位与修正

分析你代码中的问题及修复方案

我看到你在解决Project Euler第87题时得到了错误的结果,让我们一步步找出代码里的问题:

1. 质数生成方法primeNumbersTill的循环范围错误

你的primeNumbersTill方法本意是生成所有小于等于n的质数,但循环条件写成了i <= Math.sqrt(n),这会导致漏掉sqrt(n)到n之间的质数。比如当n=11时,sqrt(n)≈3.3,方法只会检查3以内的奇数,完全不会处理11这个质数。虽然在你的问题中,我们需要的质数上限分别是sqrt(5e7)、cube root(5e7)、fourth root(5e7),但错误的循环范围还是可能漏掉部分符合条件的质数(比如接近sqrt(5e7)的质数),导致后续的平方、立方、四次方列表不完整。

正确的循环范围应该是遍历从3到n的所有奇数,不过更高效的方式是直接计算每个幂次的上限,只生成需要的质数,避免生成多余的质数浪费资源。

2. isPrime方法的循环条件错误

当前isPrime的循环条件是i*i < number,这会导致无法正确判断平方数的质数性。比如判断9时,i=3时3*3=9不满足<9的条件,循环直接结束,错误地返回true(9不是质数)。

正确的条件应该是i*i <= number,同时可以添加对偶数和小于等于1的数的快速判断,提升效率:

private static boolean isPrime(int number) {
    if (number <= 1) return false;
    if (number == 2) return true;
    if (number % 2 == 0) return false;
    for (int i = 3; i*i <= number; i += 2) {
        if (number % i == 0) {
            return false;
        }
    }
    return true;
}

3. 使用Math.pow导致的精度隐患

Math.pow返回的是double类型,虽然在本题的数值范围内可能不会出现精度丢失,但对于更大的整数,double无法精确表示所有整数(超过2^53的整数会丢失精度)。而且浮点运算的效率也不如整数乘法。

应该直接使用整数乘法来计算幂次,同时用long类型进行判断避免int溢出:

// 替换Math.pow(p,2)为p*p
if ((long) p * p < n) {
    Squares.add(p * p);
}
// 立方:p*p*p
if ((long) p * p * p < n) {
    Cubes.add(p * p * p);
}
// 四次方:p*p*p*p
if ((long) p * p * p * p < n) {
    Fourth.add(p * p * p * p);
}

4. 可选优化:使用埃拉托斯特尼筛法生成质数

你的质数生成方式是逐个判断奇数是否为质数,对于较大的上限来说效率较低。使用埃拉托斯特尼筛法可以一次性生成所有小于等于上限的质数,速度快很多。

修正后的完整代码

import java.util.*;

public class Euler87 {
    public static List<Integer> sieve(int max) {
        boolean[] isPrime = new boolean[max + 1];
        Arrays.fill(isPrime, true);
        isPrime[0] = isPrime[1] = false;
        for (int i = 2; i * i <= max; i++) {
            if (isPrime[i]) {
                for (int j = i * i; j <= max; j += i) {
                    isPrime[j] = false;
                }
            }
        }
        List<Integer> primes = new ArrayList<>();
        for (int i = 2; i <= max; i++) {
            if (isPrime[i]) {
                primes.add(i);
            }
        }
        return primes;
    }

    public static void main(String[] args) {
        int n = 50000000;
        // 只需要生成到sqrt(n)的质数,因为更大的质数平方会超过n
        int maxPrime = (int) Math.sqrt(n);
        List<Integer> primes = sieve(maxPrime);

        Set<Integer> results = new HashSet<>();

        for (int p : primes) {
            long square = (long) p * p;
            if (square >= n) break; // 后续质数更大,平方也会更大,直接跳出
            for (int q : primes) {
                long cube = (long) q * q * q;
                if (square + cube >= n) break;
                for (int r : primes) {
                    long fourth = (long) r * r * r * r;
                    long sum = square + cube + fourth;
                    if (sum >= n) break;
                    results.add((int) sum);
                }
            }
        }

        System.out.println(results.size());
    }
}

这段修正后的代码应该能得到正确的结果,同时效率也更高。

内容的提问来源于stack exchange,提问作者Muki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 11:22:48