Python3.3:平方根优化

时间:2013-02-21 07:33:09

标签: python optimization python-3.x square-root

这里是Python3.3上的代码:

import sys, re, math
str1 = str(sys.stdin.readlines())
Data = re.findall('\\b\\d+\\b', str1)

for i in reversed (Data):
    print('%.4f' % math.sqrt(float(i)))

如您所见,此程序从输入中获取数据(多行随机字符串),并搜索此字符串包含的每个数字。 之后,只返回它找到的每个数字的平方根。

嗯,算法有效,但速度不够快,我不知道如何优化它。 请帮帮我。我需要做些什么来优化上面的代码?

5 个答案:

答案 0 :(得分:2)

这是一个否定的结果。我尝试使用一些技巧来加快速度,但速度要快一点。

import sys, re, math

def find_numbers(f):
    for line in f:
        for word in line.split():
            if word.isdigit():
                yield float(word)

lst = list(find_numbers(sys.stdin))
lst.reverse()
for x in lst:
    print('%.4f' % math.sqrt(x))

我认为反转列表可能会让它变慢,但是当我打印数字而没有反转时,它并没有太大的区别。

Python的最快解决方案是在PyPy中运行上面的代码。

这不是一个非常困难的问题,如果你需要速度,你可能想用C代码编写一个解决方案。 C代码将尽可能快地解决这个问题。

答案 1 :(得分:2)

您可以尝试使用Numpy加载和处理文件:

import numpy as np
for i in reversed(np.fromfile(sys.stdin, sep=' ')**0.5):
    print i

作为Python的高性能数字库,我希望它是您可以使用的最快解决方案。

答案 2 :(得分:1)

你问过Python,但这可以在C中很好地完成。这个C程序不会反转数字,但是你可以简单地通过tac程序管道输出,就像{{1}但是反转了这些行。

在我的测试中,这大约是NumPy解决方案速度的3倍,是我的Python解决方案或原始解决方案速度的6倍。

cat

答案 3 :(得分:1)

更新:发布steveha's much earlier answer副本的道歉。讲述我的阅读技巧。现在仍然在线留下这个答案,仅仅是因为我对i / o /缓冲/运行时效果的思考。

原帖:

我无法相信应用一个正则表达式并计算一个平方根需要Python更长的时间,而不是从标准输入读取一行并在标准输出上输出结果(或任何I / O) )。

由于某个时间点的I / O将来自硬盘驱动器,并且要么转到另一个硬盘驱动器或用户眼睛,这应该是限制因素。

I / O通常是为了加速而缓冲的。通常在突发中填充缓冲区,然后在等待设备提供更多数据时cpu空闲。

这会导致您的应用程序生成器。编写一个逐行读取输入的生成器,并根据需要立即提供sqrt数。我怀疑这会比任何合理的现代硬件上的整体I / O速度慢。如果您使用的是特殊设备(如嵌入式,uController,Raspberry Pi等,请告诉我们)

您可以执行的一项优化是预编译正则表达式。当你为每个测试使用相同的正则表达式时,让我们只对正则表达式进行一次解析。您在问题中的示例很好,因为您正在执行re.findall()。我只是在为其他读者详细说明。

import sys, re, math

pattern = re.compile(r'\b\d+\b')

def fh_numbers_to_sqrt(fh):
    for line in fh:
        for i in re.findall(pattern, line):
            yield math.sqrt(float(i))

numbers_g = fh_numbers_to_sqrt(sys.stdin)
for num in numbers_g:
    print('%.4f' % num)

这允许所有正则表达式和数学运算与I / O时间交错。

现在,我们根本无法真正优化和整合的一件事是reverse。算法必须等到最后一个元素能够反转。

所以我们可以将调用代码更改为:

numbers_g = fh_numbers_to_sqrt(sys.stdin)
for num in reverse(list(numbers_g)):
    print('%.4f' % num)

希望这比你原来的更快。 同样,这应该更快的唯一原因是因为我们在从标准输入读取数据所花费的挂钟时间内隐藏了正则表达式解析和计算的运行时间。这应该仍然是I / O限制。实际上reverse可能并没有真正添加到整个运行时,因为它可能与标准输出上发生的I / O交错。看一下挂钟,这个算法可能根本没用。 : - )

为了证明或否定我的整个帖子,您可以使用time.time()衡量从脚本开始到行Data = re.findall之前,从那时到结束的时间。如果我是正确的,那么数据读取将占用大部分时间。如果没有,那么也值得测量所有正则表达式搜索所需的时间。让我们知道。我好奇......

答案 4 :(得分:0)

import sys, re, math
str1 = str(sys.stdin.readlines())
Data = re.findall('\\b\\d+\\b', str1)

d2 = [round(math.sqrt(float(i)),4) for i in reversed (Data)]

for i in d2:
    print(i)