C 我是不是刚证明了埃拉托什尼的筛子比试验组的效率低?
我试着比较两种算法的运行时速度:一个用于打印素数(10000个数)的蛮力C程序,和一个用于筛选埃拉托斯特尼C程序(也有10000个素数) 我测量的sieve算法的运行时间是:0.744秒 我测量的蛮力算法的运行时间是:0.262秒C 我是不是刚证明了埃拉托什尼的筛子比试验组的效率低?,c,algorithm,primes,performance,sieve-of-eratosthenes,C,Algorithm,Primes,Performance,Sieve Of Eratosthenes,我试着比较两种算法的运行时速度:一个用于打印素数(10000个数)的蛮力C程序,和一个用于筛选埃拉托斯特尼C程序(也有10000个素数) 我测量的sieve算法的运行时间是:0.744秒 我测量的蛮力算法的运行时间是:0.262秒 然而,有人告诉我,Eratosthenes算法的筛子比蛮力方法更有效,因此我认为它会运行得更快。因此,要么我错了,要么我的程序有缺陷(我对此表示怀疑) 因此,我的问题是:因为我得到了与我预期相反的结果,这是否证明了埃拉托斯坦筛在速度方面真的是比尝试除法效率更低的算法?
然而,有人告诉我,Eratosthenes算法的筛子比蛮力方法更有效,因此我认为它会运行得更快。因此,要么我错了,要么我的程序有缺陷(我对此表示怀疑) 因此,我的问题是:因为我得到了与我预期相反的结果,这是否证明了埃拉托斯坦筛在速度方面真的是比尝试除法效率更低的算法?
我不确定它是否有任何关联,但我使用的是DEV C++编译器和Windows 7。
一般:是的,但是当你在1秒的范围内时,会有很多噪音,可能会混淆……/P> 多次运行每个测试,并对结果使用一些统计数据(例如,平均值或平均值/偏差,取决于您的关注程度)
和/或让它做更多的工作,比如找到更多的素数。简言之,是的,如果效率是指时间效率的话。还有内存方面的考虑。
不过要小心你的测量方法——确保你的计时工具是精确的。
确保在没有其他设备运行时在同一台机器上进行测量。
确保你测量了几次,取平均值和方差进行比较。
考虑让别人检查你的代码,检查它是怎么做的。 < P>不,经过运行的时间不是衡量效率的标准,因为它从平台到平台不同——说“我的算法在10秒内运行”对算法本身几乎没有任何信息。除此之外,您还需要列出整个环境规范和同时运行的其他进程,这将是一个巨大的混乱。因此,顺序符号的发展(大Oh、小Oh、ω等) 效率通常分为两个子部分:
n
所需执行的指令量时,算法根据其渐近行为进行分析。这是一个非常高层次的解释,这个领域是由博士计算机科学家精心研究的——我建议你阅读更多关于它的内容,以获得你会找到的最好的低层次解释
注意,我附上了Big-Oh注释的链接——姐妹注释都可以在维基百科页面上找到,这通常是一个很好的开始。它还将涉及到空间效率和时间效率的差异
使用大Oh的时间效率小应用:
考虑一下Racket中的以下递归函数(如果我知道的话,将是Python中的递归函数——我能做的最好的伪代码):
。。。我们看到:empty?
,rest
,
和first
都是O(1)。我们还注意到,在最坏的情况下,input\u a
的第三个条件和第四个条件分别调用fn\u a
。然后我们可以把我们的递推关系写成,T(n)=O(1)+2T(n-1)。在递归关系图上查找,我们看到fn_a
的顺序为O(2^n),因为在最坏的情况下,会进行两次递归调用
同样重要的是要注意,根据大Oh的正式定义,指出fn_a
是O(3^n)也是正确的(尽管毫无用处)。当分析时,很多算法都是用大θ表示的,但是更适合用大θ来收紧边界,本质上是指:相对于给定算法的最低、最准确的顺序
小心,阅读正式定义 算法的效率通常通过它们处理大量输入的效率来衡量。10000个数字并不是一个很大的输入,所以在埃拉托斯坦的筛选开始变得更快之前,您可能需要使用一个更大的数字 或者,在您的一个实现中可能存在一个较大的问题 最后,算法的效率可以通过所需的内存量来衡量(但这种衡量方法不太常见,尤其是因为现在内存非常便宜) 运行时间较长是否意味着算法效率较低 没有必要。程序的效率不仅取决于所花费的时间,还取决于所花费的资源。在考虑效率时,空间是另一个需要牢记的因素 从:- 为了最大限度地提高效率,我们希望尽量减少资源使用。然而, 各种资源(如时间、空间)无法直接比较, 那么,这两种算法中哪一种通常被认为更有效 取决于哪种效率衡量标准被认为是最重要的 重要信息,例如,是要求高速还是最低速度 内存使用率,还是其他指标 TL;DR:仅在一个输入大小下比较代码变体的速度是毫无意义的;比较经验增长顺序确实反映了代码的算法性质,对于相同的输入大小测试范围,在不同的测试平台上是一致的。比较绝对速度值仅对表现出相同渐近或至少局部增长行为的代码变体有意义
仅仅在一个输入大小下测量两个实现的速度是不够的。通常需要几个数据点来评估代码的运行时间(因为代码可以使用
(define (fn_a input_a)
(cond
[(empty? input_a) empty]
[(empty? (rest input_a)) input_a]
[(> (first input_a) (fn_a (rest input_a))) (cons (first input_a) empty)]
[else (fn_a (rest input_a))]))