我正试图从http://projecteuler.net解决问题3。但是,当我运行程序时,没有打印出来。 我究竟做错了什么? 问题:600851475143号码的最大素数因素是什么?
public class project_3
{
public boolean prime(long x) // if x is prime return true
{
boolean bool = false;
for(long count=1L; count<x; count++)
{
if( x%count==0 )
{
bool = false;
break;
}
else { bool = true; }
}
return bool;
}
public static void main(String[] args)
{
long ultprime = 0L; // largest prime value
project_3 object = new project_3();
for(long x=1L; x <= 600851475143L; x++)
{
if( object.prime(x)==true )
{
ultprime = ((x>ultprime) ? x : ultprime);
}
}
System.out.println(ultprime);
}
}
答案 0 :(得分:7)
您的prime
检查功能不仅始终返回false
;即使它运行正常,你的主循环根本不会寻找输入数字的因子,而只是寻找小于或等于它的最大素数。在伪代码中,您的代码等同于:
foo(n):
x := 0 ;
foreach d from 1 to n step 1:
if is_prime(d): // always false
x := d
return x // always 0
is_prime(d):
not( d % 1 == 0 ) // always false
但是你根本不需要素数检查功能。以下内容通过trial division查找数字的所有因子:
factors(n):
fs := []
d := 2
while ( d <= n/d ):
if ( n % d == 0 ): { n := n/d ; fs := append(fs,d) }
else: { d := d+1 }
if ( n > 1 ): { fs := append(fs, n) }
return fs
可分性测试仅在数字的平方根处进行。如所发现的,每个因子被分解出被分解的数量,从而进一步减少了运行时间。所涉及数量的因子分解立即运行,仅需1473次迭代。
通过构造,这样找到的所有因素都是保证是素数(这就是为什么不需要进行素数检查的原因)。在升序中枚举可能的除数至关重要,以使其发生 1 。升序也是效率最高的,因为任何给定的数字更可能具有比较大的素数小的素数因子。枚举 primes 而不是赔率,虽然没有必要,但如果你有一种有效的方法来获得这些素数,那么将更有效率来测试除以。
增加上述内容以找到最大因素是微不足道的:只需将append
实现为
append(fs,d):
return d
1
因为当原始数字的任何复合除数d
被分解时,当我们到达d
时,我们已经将其素数因子除以原始数,因此减少了数字将没有共同的素数因子,即d
即使它除以原始数据也不会对减少的数字进行除法。
答案 1 :(得分:3)
两件事:
1)您从1开始count
而不是2.所有整数都可以被1整除。
2)你正在对一个相当大的N运行一个O(n ^ 2)算法(或者至少你会在你修复点#1时)。运行时间很长。
答案 2 :(得分:2)
Project Euler的重点是找到答案最明显的方法需要很长时间来计算它们不值得运行。这样你就可以学会寻找不那么明显,更有效的方法。
您的方法在技术上是否正确,无论它是否能够计算某个数字的最大素数。您没有看到任何打印输出的原因是您的算法无法快速解决问题。
你设计这个的方式,需要大约4,000,000年才能完成。
如果用20表示替换了600851475143号码,它将能够相当快地完成。但是你拥有6000亿的数字,所以它并不那么简单。