使欧拉计划的解决方案更加高效
最初,我在让这段代码运行时遇到了一些问题,但经过一些调整后,我对其进行了调试并准备就绪。
我对这个程序进行了多次修改。我从整数值开始,却发现这个数字太大,无法放入 int 中。然后我改用 BigIntegers,事实证明这很麻烦,但可行。从那时起,我切换到长整型(就像从一开始就应该做的那样)并将代码的运行时间缩短了 8 倍(或更多)。
这是现在的代码:
long qNum = 600851475143L;
for (long i = qNum - 1L; i * i >= qNum; i -= 2L)
if (qNum % i == 0 && isPrime(i)) {
System.out.println("Solution:" + i); // for debugging
return i;
}
else
System.out.println(i);// for debugging
return 0L;
它
public static boolean isPrime(long num) {
// unnecessary if statement for this problem (b/c of for loop), but useful for others
if (num % 2 == 0)
return false;
for (long i = 3; i * i <= num; i += 2)
if (num % i == 0)
return false;
return true;
}
已经运行了多个小时,但仍然没有找到任何东西。我在网上看到解决这个难题的典型方法是解析560GB的数据=/。
有什么加快速度的技巧吗?
非常感谢,
Justian
编辑:
优化代码:
public static long greatestPrimeFactor(ArrayList<Long> factors, long num) {
for (long i = 2; i <= Math.sqrt(num); i++) {
if (num % i == 0) {
factors.add(i);
return greatestPrimeFactor(factors, num / i);
}
}
for (int i = factors.size()-1; i > 0; i--)
if (isPrime(factors.get(i)))
return num;
return 0;
}
AND
public static boolean isPrime(long num) {
if (num % 2 == 0)
return false;
for (long i = 3; i * i <= num; i += 2)
if (num % i == 0)
return false;
return true;
}
RUN WITH
greatestPrimeFactor(new ArrayList<Long>(), 600851475143L);
Originally, I was having some issues getting this code to function, but after a little tweaking I got it debugged and ready to go.
I have gone through several revisions of this program. I started with integer values only to find that the number was too large to fit into an int. I then changed to BigIntegers, which proved to be a hassle, but workable. From there, I switched to longs (as should have done from the beginning) and cut the runtime of my code 8-fold (or more).
Here's the code as it is now:
long qNum = 600851475143L;
for (long i = qNum - 1L; i * i >= qNum; i -= 2L)
if (qNum % i == 0 && isPrime(i)) {
System.out.println("Solution:" + i); // for debugging
return i;
}
else
System.out.println(i);// for debugging
return 0L;
And
public static boolean isPrime(long num) {
// unnecessary if statement for this problem (b/c of for loop), but useful for others
if (num % 2 == 0)
return false;
for (long i = 3; i * i <= num; i += 2)
if (num % i == 0)
return false;
return true;
}
It's been running for multiple hours and it still hasn't found anything. I saw online that solving this puzzle the typical way is like parsing 560GB of data =/.
Any tips for speeding this up?
Many thanks,
Justian
EDIT:
Optimized code:
public static long greatestPrimeFactor(ArrayList<Long> factors, long num) {
for (long i = 2; i <= Math.sqrt(num); i++) {
if (num % i == 0) {
factors.add(i);
return greatestPrimeFactor(factors, num / i);
}
}
for (int i = factors.size()-1; i > 0; i--)
if (isPrime(factors.get(i)))
return num;
return 0;
}
AND
public static boolean isPrime(long num) {
if (num % 2 == 0)
return false;
for (long i = 3; i * i <= num; i += 2)
if (num % i == 0)
return false;
return true;
}
RUN WITH
greatestPrimeFactor(new ArrayList<Long>(), 600851475143L);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
你做了太多不必要的事情。这是一个更简单的解决方案:
You are doing too many unnecessary things. Here's a simpler solution:
您不需要测试每个数字是否是质数。您看到了这一点,因此您只测试每个奇数(好吧,还有 2)。你可以更进一步!快速构建一个包含前几百万个素数的表,并且仅针对这些素数进行测试。你会走得更快,而且开销很小。
编辑:这就是我所说的。这非常简单。请注意我如何仅将这些值与已计算的素数进行比较。一旦您计算出相当数量的素数(例如,前 10000000 个素数),就开始像您一样基于 +2 方法进行搜索。请记住,大多数人都会很早就被发现,因为您跳过了不必要的数字。您不需要测试 15,25,35,45,55 等,因为您已经测试了 5。这本身就会剔除大约 20% 的测试,这很容易计算出计算最初的几百万个数字。
示例输出
示例代码:
You don't need to test every number for whether or not it is prime. You see this, so you only test every ODD number (well, and 2). You can take this further! Construct a table of the first few million primes quickly, and only test against those. You'll go a LOT faster, with a very small overhead.
Edit: Here's what I was talking about. It's quite straightforward. Notice how I only compare the values to already computed primes. Once you've computed a fair number of them (say, the first 10000000 primes) start doing your search based on on the +2 method like you are. Keep in mind that most of them are going to get caught early because you're skipping unnecessary numbers. You don't need to test 15,25,35,45,55, etc, because you already tested 5. That in and of itself is going to cull about 20% of your tests, which easily accounts for the overhead of calculating the first few million numbers.
Sample output
Sample code:
在 python 中,您可以计算所有质因数,然后使用 max 函数,如下所示:
In python, you can just calculate all the prime factors and then use the max function, like so:
我的解决方案在不到百分之一秒的时间内完成。每次找到该数字的除数时,将该数字除以该除数,然后重新开始。您除以的最大数字就是您的目标。
My solution hits in less than a hundredth of a second. Each time you find a divisor of the number, divide the number by that divisor and start again. The highest number you divide by is your target.