[英]How can I make this Project Euler solution execute in Python at the same speed as Java?
在任何人开始之前,我知道在编程语言中谈论“速度”并不总是最有用的讨论。 也就是说,速度是这里的问题。
我用两种语言解决了Project Euler问题5 ,虽然我在两种语言中的实现看起来与我的眼睛非常相似,但运行时却大不相同。 Java只需几秒钟即可返回答案,而Python最多可能需要一分钟(当然,在同一台机器上)。 我很确定这不是Python的错,更不是程序员(我)的错,他们还没有学会用Python来学习。
请注意, 我不是要求您重写我的代码 。 我只是在朝着正确的方向寻找一些推动力。 (是的,我看过一些 类似的 线程,但大多数都是我的头脑,并没有直接比较两种语言中的相同算法。 这个线程很有用,但同样,不直接比较Java和Python -坦率地说,答案有点难以理解。)
无需再费周折:
public class Problem5 {
public static void main(String[] args){
boolean found = false;
for (int i = 20; !found; i += 20){
if (DivisThrough20(i)) {
found = true;
System.out.println(i);
}
}
}
private static boolean DivisThrough20(int number){
boolean result = true;
for (int i = 19; result && i > 1; i--){
if (number % i != 0) result = false;
}
return result;
}
}
def DivisThroughTwenty(number):
for x in range(20,1,-1):
if number % x != 0:
return False
return True
# the number we're looking for can't be any lower than 20, so we'll
# start there as a small optimization
testNumber = 20
keepLooking = True
while keepLooking:
if not DivisThroughTwenty(testNumber):
testNumber += 20
else:
keepLooking = False
print testNumber
有趣的是,并排阅读这些我已经可以看到这个算法的Python版本比Java版本稍微优化一点,但它仍然慢得多。 我现在更好奇的是找到解决问题的另一种方法。
Python是一种动态类型语言,而Java是一种静态类型语言。 这意味着Java在编译时有更多关于变量类型的信息,特别是数字。 Java的设计人员花了相当多的精力来定义JVM,以便32位( int
)和64位算术( long
)计算能够以有效的方式工作。
另一方面,Python没有变量类型声明,因此像x
这样的变量可以保存任何对象。 在你的情况下,碰巧他们总是持有数字,但CPython的编译器并没有去验证它。 当Python执行你的代码时,评估一个表达式,例如number % x
包括查找%
运算符以查找由number
表示的对象,调用%
运算符,获取x
的类型,确保它是兼容的数字类型等。所有这些都需要时间,特别是当你做了数十万次时。
替代Python实现(如PyPy)会努力尝试确定变量的类型。 在您的情况下,它可以确定number
和x
始终引用整数 ,并生成不必检查类型的适当的低级代码。
最后,您可能希望查找最小公倍数,以便以任何语言更快地解决Project Euler问题。 与Project Euler问题一样,最快的解决方案不是通过编写更快的代码,而是通过选择合适的算法。
我不确定这可能有多大帮助,但你的工作代码可以用更加pythonic的方式重写,如下所示:
def divis_through_twenty(n):
return any(n % x for x in xrange(20,1,-1))
x = 20
while divis_through_twenty(x):
x += 20
print x
如果你愿意,你可以更多地优化它(例如,如果你已经测试了一个数字可被20整除,你不需要检查它是否可以被10,5或2整除)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.