我正在学习算法,并决定将教科书中的Java程序移植到Python,因为我不喜欢Java的开销,特别是对于小型程序,这也是一种练习。
该算法本身非常简单,它只是以一种暴力的方式从数组中取出所有三元组,并计算有多少个三元组的总和为零(例如:[-2,7,-5])。
我把它移植到了:
当然,这并不是一个好的算法,这只是展示了这个问题在这里和教科书中。我之前在Java和Python中都写过一些编程,但没有意识到这种巨大的差异。
问题归结为:如何克服这个问题?更具体地说:
1. 这段代码是否是一个好的端口,或者我错过了一些微不足道的东西? 2. 切换到另一个运行时(例如Jython)是否是一个解决方案?是否容易在eclipse中保持我的代码库并添加一个解释器(编译器)?或者切换到另一个解释器/编译器只会使事情稍微好一点?
我现在正在使用Windows 7上的python 2.7.3和Java 1.7 32ibts。
我知道SO上有类似Java/Python性能的问题,但像Python中存在不同的运行时环境这样的答案对我目前没有帮助。
我想知道的是,这些运行时环境中是否有一些可以弥补这个巨大差距的,并且值得探索?
更新:
我安装了pypy,现在差异非常大...
更新2:
我注意到一些非常有趣的事情:这里的islice方法在“常规”Python上更快,但在pypy上要慢得多。即使是这样,pypy仍然比使用常规循环或islices的algoritm快得多。
正如Bakuriu在备注中指出的那样,运行时环境可能非常重要,但对于这个算法更快的运行时环境不一定对于任何算法都更快...
该算法本身非常简单,它只是以一种暴力的方式从数组中取出所有三元组,并计算有多少个三元组的总和为零(例如:[-2,7,-5])。
public static int count(int[] a) {
int N = a.length;
int cnt = 0;
for (int i = 0; i < N; i++) {
for (int j = i+1; j < N; j++) {
for (int k = j+1; k < N; k++) {
if (a[i] + a[j] + a[k] == 0) {
cnt++;
}
}
}
}
return cnt;
}
我把它移植到了:
def count(a):
cnt = 0
ln = len(a)
for i in xrange(0,ln):
for j in xrange(i + 1,ln):
for k in xrange(j + 1,ln):
if a[i] + a[j] + a[k] == 0:
cnt+=1
return cnt
现在只是测量这些功能需要:
java : array of 2000 elements --> 3 seconds
python : array of 2000 elements --> 2 minutes, 19 seconds
UPDATE
python (pypy) : array of 2000 elements --> 4 seconds ( :-) )
当然,这并不是一个好的算法,这只是展示了这个问题在这里和教科书中。我之前在Java和Python中都写过一些编程,但没有意识到这种巨大的差异。
问题归结为:如何克服这个问题?更具体地说:
1. 这段代码是否是一个好的端口,或者我错过了一些微不足道的东西? 2. 切换到另一个运行时(例如Jython)是否是一个解决方案?是否容易在eclipse中保持我的代码库并添加一个解释器(编译器)?或者切换到另一个解释器/编译器只会使事情稍微好一点?
我现在正在使用Windows 7上的python 2.7.3和Java 1.7 32ibts。
我知道SO上有类似Java/Python性能的问题,但像Python中存在不同的运行时环境这样的答案对我目前没有帮助。
我想知道的是,这些运行时环境中是否有一些可以弥补这个巨大差距的,并且值得探索?
更新:
我安装了pypy,现在差异非常大...
更新2:
我注意到一些非常有趣的事情:这里的islice方法在“常规”Python上更快,但在pypy上要慢得多。即使是这样,pypy仍然比使用常规循环或islices的algoritm快得多。
正如Bakuriu在备注中指出的那样,运行时环境可能非常重要,但对于这个算法更快的运行时环境不一定对于任何算法都更快...
cnt = sum(1 for x in xrange(0, ln-3) if not sum(a[x:x+3]))
。 - l4mpipsycho
运行你的算法,你可能会看到类似于PyPy的结果。(不幸的是它已经不再维护了)。 - Bakuriu