C 语言 clock() 函数,例:计算多项式值

您所在的位置:网站首页 c语言clock计时一直为0 C 语言 clock() 函数,例:计算多项式值

C 语言 clock() 函数,例:计算多项式值

#C 语言 clock() 函数,例:计算多项式值| 来源: 网络整理| 查看: 265

C 语言 clock() 函数,例:计算多项式值 /** * clock(): 捕捉从程序开始运行到 clock() 被调用时所耗费的时间。 * 这个时间单位是 clock tick, 即“时钟打点”。 * 常数 CLK_TCK: 机器时钟每秒所走的始终打点数。 * In Macintosh or C99, CLK_TCK == CLOCKS_PER_SEC * http://www.cplusplus.com/reference/ctime/CLOCKS_PER_SEC/ */

我把老师说的话都敲了一遍哈哈。为了测试两种算法,哪一种的效率更高,我们就需要有一个工具来记录这个算法做完这件事花费了多长时间。clock() 函数就是 C 语言所提供的工具,当然其他的语言也有,找找就能找到的。

例:写程序计算给定多项式在定点 \(x\) 处的值

\[f(x) = a_0 + a_1x + a_2x^2 + ... + a_{n-1}x^{n-1} + a_nx^n \]

double f1(int n, double a[], double x) { int i; double p = a[0]; for (i = 1; i 0; i--) p = a[i-1] + x*p; return p; }

令 p 从 a[n] 开始,然后每一次用 x 乘以这个括号里面已经算出来的这个 p,然后再加上前面那一项的系数 a[i-1]。

那,凭什么说第二个函数就比第一个函数实现得要好呢?凭什么第一个函数就要被鄙视呢?因为第一个函数慢好多。到底谁快谁慢呢?不服气的话,我们要来测一下

clock() 函数

那在 C 语言里头呢,提供了一个这样的工具。C 语言提供了一个函数,叫做 clock。这个函数可以捕捉从程序开始运行,一直到这个函数被调用那个时刻所耗费的时间,但是它这个时间的单位,是 clock tick,翻译成“时钟打点“。跟它配套的,我们还有一个常数,叫 CLOCKS_PER_SEC (在 C99 以前,叫 CLK_TCK,实际上就是 clock tick 的一个缩写),给出的是这个机器时钟每秒钟走的时钟打点的数。那这个数到底等于多少呢?不同的机器可能都不一样。这两个东西配合在一起我们就可以算出来一个函数到底跑了多少秒钟。

#include #include /* for clock() */ clock_t start, stop; /* clock_t 是 clock() 函数返回的变量类型 */ double duration; /* 记录被测函数运行时间,以秒为单位 */ int main() { /* 不在测试范围内的准备工作写在 clock() 调用之前 */ start = clock(); /* 开始计时 */ foo(); /* 把被测函数加在这里 */ stop = clock(); /* 停止计时 */ duration = ((double)(stop-start))/CLOCKS_PER_SEC; /* 其他不在测试范围的处理写在后面,例如输出 duration 的值 */ return 0; }

foo() 函数,就是你要测的函数。这里的命名呢涉及到历史遗留问题,在很多的例子代码中,有的变量或者函数的命名是 foo。foobar 是计算机程序领域里的术语,并无实际用途和参考意义。在计算机程序设计与计算机技术的相关文档中,术语 foobar 是一个常见的无名氏化名。

clock() 函数返回的是从这个程序开始运行,直到调用的那个时刻所耗费的时间。所以在函数开始之前调用 clock() 存到 start 这个变量里面,在函数执行结束之后,紧接着又调用一次 clock(),存到 stop 这个变量里边。那么 stop 里边存的是什么呢?就是 main() 函数开始执行,一直到这次 clock 被调用的时候,一共走了多少个 ticks。所以我们用 stop - start 就得到了 foo() 的执行过程中间一共经历了多少个 ticks,最后我们再除一下这个常数,就得到了以秒为单位的这个 duration。

下面我们就一个具体的多项式来看一下,计算 \(x\) = 1.1 处的值 \(f(1.1)\)

\[f(x) = \sum_{i=0}^{9}i \cdot x^i \]

它的系数呢,我们就让第 i 个系数就等于 i 好了。然后我们来跑一下,看看它们分别跑了多少时间。

#include #include /* for pow() */ #include /* for clock() */ #define MAXN 10 /* 多项式最大项数,即多项式阶数+1 */ int main() { int i; double a[MAXN]; /* 存储多项式的系数 */ for (i = 0; i < MAXN; i++) a[i] = i; start = clock(); f1(); stop = clock(); duration = ((double)(stop-start))/CLOCKS_PER_SEC; printf("ticks1 = %f\n", (double)(stop-start)); printf("duration1 = %f\n", duration); start = clock(); stop = clock(); duration = ((double)(stop-start))/CLOCKS_PER_SEC; printf("ticks2 = %f\n", (double)(stop-start)); printf("duration2 = %f\n", duration); return 0; }

当然你现在看起来呢,说这真是一个很傻的程序。因为没有一个很专业的程序员可以容忍说,我一段代码里头,居然有两个片段几乎是一模一样的。如果你看到这种情况,重复的情况,你应该怎么去做一个更好的处理呢?显然你应该会写一个函数去做这件事情。Anyway (无论如何),先跑一下。跑出来的结果有可能都是 0,这是因为这两个函数跑得实在是太快了,它们的运行时间都不到一个 tick,所以 clock() 函数根本捕捉不到它的区别。那这怎么办呢?如何测出不到1个tick的程序运行时间?重复

跑一次捕捉不到,跑 10 次、跑 100 次、跑 1000 次、跑 10000 次,积累一点运行时间,一直跑到间隔的时间能够被 clock() 捕捉到。最后计算单次时间的时候,你只要把总时间除以重复的次数,你就得到了这个函数一次运行的时间。

你将看到这两组数据的相对大小,应该都是差了一个数量级这个样子。所以我们就可以看到,为什么说第一个算法比较傻呢,它比第二个算法要慢了差不多一个数量级的样子。这个故事告诉我们,解决问题方法的效率,跟算法的巧妙程度有关。

再试一个多项式

给定另一个100阶多项式 \(f(x) = 1 + \sum_{i=1}^{100} \frac{x^i}{i}\),用不同方法计算 \(f(1.1)\) 并且比较一下运行时间?



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3