为了重新学习如何用Java编写代码,我一直在经历Project Euler的一些问题。我写的以下代码是解决问题3:找到数字600851475143的最大素数因子。
public class ProjectEuler {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
ProjectEuler t = new ProjectEuler();
System.out.println(t.findLargestPrime(600851475143L));
}
public Boolean isPrime(int x) {
Boolean answer = true;
for (int i = 2; i < x/2; i++) {
if (x%i == 0) {
answer = false;
}
}
return answer;
}
public int findLargestPrime(Long max) {
int largest = 1;
for (int i = 2 ; i < max/2; i++) {
if (max%i == 0 && isPrime(i) && i > largest) {
largest = i;
}
}
return largest;
}
}
然而,当我运行它时,代码抛出算术错误,因为我试图除以零?这里显示了实际的错误消息:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at projecteuler.ProjectEuler.findLargestPrime(ProjectEuler.java:37)
at projecteuler.ProjectEuler.main(ProjectEuler.java:19)
我不知道我是否在某个地方犯了一个愚蠢的错误,或者这是一个我不明白的Java怪癖?任何人都可以对此有所了解吗?
谢谢。
答案 0 :(得分:7)
for (int i = 2 ; i < max/2; i++)
最终会溢出(因为600851475143 / 2
大于Integer.MAX_VALUE
),最终i
将等于0
max%i
i
将抛出该异常。
如果您想阻止它发生,请将long
更改为int
(您还应将所有其他long
更改为 <Grid VerticalAlignment="top" Margin="0,40,0,0" Background="White">
<ContentPresenter
/>
</Grid>
)。< / p>
答案 1 :(得分:0)
这不是实际问题的答案,但是:您不必检查最多max
的所有数字,甚至不需要检查除数是否为素数。您只需(反复)将max
除以您找到的任何除数i
。
long l = 600851475143L;
for (int i = 2; i <= Math.sqrt(l); i++) {
if (l % i == 0) {
System.out.println(i);
l /= i;
i--;
}
}
System.out.println("--> " + l);
这样,你知道这个除数必须是素数 - 如果它是复合的,max
已经被它的分量除。这也意味着你不必一直循环到max
(对于给定的值,这将花费很长时间),但只能达到最大的素数除数,这可能是多少小。一旦达到sqrt(l)
- 当前值为l
,而不是原始版本! - 你可以停止,因为不会有任何高于此的除数,l
的剩余值将是最终的(因此也是最大的)素数因子。
因此,这将复杂性从大约O(n²)降低到大约O(n 1/2 )。