所以我有一个问题,我已经在python和java中解决了。问题是,对于8000 * 8000个元素的乘法表,找到所有唯一的数字:
Python:
table = 8000
unique_prods = []
start = 1
for i in range(table*table + 1):
unique_prods.append(0)
for x in range(1, table + 1):
for y in range(start, table + 1):
# print '{:4}'.format(x * y),
if not unique_prods[x * y] == x * y:
unique_prods[x * y] = x * y
start += 1
# print
# print unique_prods
print len(unique_prods)
爪哇:
public class Test {
public static void main(String[] args) {
int table = 8000;
int [] myArray = new int[table*table + 1];
int count = 1;
for (int i = 0; i < table*table + 1; i++) {
myArray[i] = 0;
}
for (int x = 1; x < table + 1; x++) {
for (int y = count; y < table + 1; y++) {
if (! (myArray[x * y] == x * y)) {
myArray[x * y] = x * y;
}
}
count += 1;
// System.out.println(count);
}
count = 0;
for (int i = 0; i < table*table + 1; i++) {
if(myArray[i] != 0) {
count += 1;
}
}
System.out.println(count);
}
}
我发现令人惊讶的是Java实现花了一秒钟,Python版本花了一分钟。有没有办法提高python性能,使其更接近Java实现的速度?
答案 0 :(得分:2)
你的Python代码不是最优的,你不会像在Java中那样解决问题:
table = 8000
unique_prods = set()
for x in range(1, table + 1):
for y in range(x, table + 1):
unique_prods.add(x * y)
print len(unique_prods)
我的电脑需要14秒。 但很明显,python需要更长时间才能解决数学问题,因为Python没有集成的JIT-Compiler。对于计算,有一个名为numpy的包,可以大大加快速度:
import numpy
x = numpy.arange(1,8001)
unique_prods = numpy.zeros(8000*8000+1,dtype='b')
for k in x:
unique_prods[k*x[k-1:]]=1
print unique_prods.sum()
你的结果是0.8秒。与C版本相比,只需要0.6秒。
答案 1 :(得分:0)
Python可能会更慢,但请将以下两个片段视为更多pythonic:
import time
starttime = time.time()
table = 8000
unique_prods = [0] * (table*table + 1)
for x in range(1, table+1):
for y in range(1, table+1):
unique_prods[x*y] = 1
elapsed = time.time() - starttime
print((elapsed, sum(unique_prods)))
最简单,但不一定最快:
starttime = time.time()
table = 8000
unique = set(x*y for x in range(1, table+1) for y in range(1,table+1))
elapsed = time.time() - starttime
print((elapsed, len(unique)))
Python并不是最快的。 python的优点是你可以编写
unique = set(x*y for x in range(1, table+1) for y in range(1,table+1))
print(len(unique))
基本上是一个明确解决潜在数学问题的单线程,即定义一个集合并打印其基数。
答案 2 :(得分:0)
问题似乎在于如何在python中创建数组。
请考虑以下事项:
array = []
for i in range(8000*8000 + 1):
array.append(0)
这需要很长时间才能运行(对我来说是14秒),因为我们首先创建一个空数组,然后调整它总共64000001次。您应该创建一个正确大小的数组,而不是这样做,这样只需要一个内存分配:
array = [0] * (8000*8000 + 1) // Creates an array filled with zeros of size (8000*8000 + 1)
这段代码几乎立即就出现了。
答案 3 :(得分:0)
正如其他人已经注意到的那样,扩展列表的方式是支持这种算法的Java实现的一件事。这个简单的修复:
unique_prods = [0] * (table*table + 1)
会产生以下算法结果(实施方式与您发布的完全相同):
python -m timeit -n 10 -r 1 "import test" "test.testWithFix()"
64000001
64000001
64000001
64000001
64000001
64000001
64000001
64000001
64000001
64000001
10 loops, best of 1: 31.6 sec per loop
python -m timeit -n 10 -r 1 "import test" "test.testWithoutFix()"
64000001
64000001
64000001
64000001
64000001
64000001
64000001
64000001
64000001
64000001
10 loops, best of 1: 62.9 sec per loop
此外,您的实现都是错误的(您应该使用一组)并且还有其他一些小错误(如评论中提到的冗余if
语句)。