目录
前言
当你对于一个问题存在多种解法时,是否难以弄清哪一种方法更加巧妙?
本篇文章来教大家通过使用clock()函数设计一个捕捉被测函数运行时间的程序。
(注:1.文中代码段由作者自己编写,若有纰漏或错误,欢迎大家指正;2.文中部分代码段仅为参考模板,请朋友们根据需求进行修改;3.作者本人为初学者,编程水平有待提高,所写博客皆为本人的笔记和一些简单知识的分享,还望各位路过的大佬嘴下留情)
基础版:两个被测函数的效率比较
这里为大家提供一个较为简单且容易理解的基础方法,但仅用于两个被测函数的比较。
下面具体为大家介绍关于c语言中的clock()函数的原理及其用法,我们利用clock()函数来捕捉两种程序在运行过程中所使用的时间。
clock():捕捉从程序开始运行到clock()函数被调用时所耗费的时间。
clock tick:是一个时间单位,即“时钟打点”。
CLK_TCK:是一个常数,即机器时钟每秒所走的时钟打点数(每台机器的此常数也是不同的)。
下面为大家提供clock()函数的一个使用模板:
//模板一
#include<stdio.h>
#include<time.h> //需要调用clock()函数
//定义全局变量
clock_t start, stop;//clock_t为time.h头文件中的一种数据类型
double duration; //定义程序运行时间为浮点型,且以秒为单位
//声明函数部分
void way1(); //被测函数一
void way2(); //被测函数二
void check(int x,int case_n); //检测程序运行时间
//主函数部分
int main()
{
//调用check()函数返回运行时间
check(1,1);
check(2,2);
}
//定义函数部分
void check(int x,int case_n)
{
//不在测试范围内的准备工作及处理应写在clock()函数调用的前后
start = clock(); //开始计时(从程序开始运行到被调用)
(x == 1) ? way1() : way2();
stop = clock(); //停止计时(从程序开始运行到被调用)
duration = ((double)(stop - start)) / CLK_TCK; //stop与start之差即为被测函数所使用的时间(时钟打点数),将其结果强制转换为double型
//再比上时间常数(上文已给出相关概念),便得出程序运行所需秒数
printf("case%d:运行时间:%f\n", duration);
printf(" 打点数:%f\n", (double)(stop - start));
}
void way1()
{
//被测函数一
}
void way2()
{
//被测函数二
}
当我们着手运行程序时,有时会遇到一种问题,为何运行结果全为0呢?(见下图)
这是因为程序运行太快,colck()函数无法捕捉其运行时间。
在此提出解决方法:让被测函数重复运行多次次,使得测出的总的时钟打点间隔充分长,最后计算被测函数平均每次运行的时间即可!
for (int i = 0; i < 1e7; i++)
{
(x == 1) ? way1() : way2(); //重复调用函数以获得充分多的时钟打点数
}
使用模板一进行举例:
(捕捉针对解决多项式问题的两种方法的运行时间,小伙伴对此有兴趣的话,可点击下方链接阅读进行详细了解)(1条消息) 关于算法效率——通过写程序计算给定多项式在给定点X处的值_小小Vegetable的博客-CSDN博客https://blog.csdn.net/qq_75151748/article/details/128543366?spm=1001.2014.3001.5502
//解决多项式问题的两种方法
#include<stdio.h>
#include<time.h> //需要调用clock()函数
#include<math.h> //需要调用pow()函数
//定义全局变量
clock_t start, stop;//clock_t为time.h头文件中的一种数据类型
double duration; //定义程序运行时间为浮点型,且以秒为单位
#define N 10 //拟定项数的最高次N为10
#define unknowN 2.2 //拟定未知数的大小为2.2
//声明函数部分
double way1(double arr[]); //被测函数一
double way2(double arr[]); //被测函数二
void check(int x, double arr[],int case_n);//检测程序运行时间
//主函数部分
int main()
{
int i;
double arr[N]; //存储多项式的系数
for (i = 0; i < N; i++)
{
arr[i] = (double)i;//即arr[i]=i;
}
//调用check()函数返回运行时间
check(1, arr,1);
check(2, arr,2);
}
//定义函数部分
void check(int x,double arr[],int case_n)
{
//不在测试范围内的准备工作及处理应写在clock()函数调用的前后
start = clock(); //开始计时(从程序开始运行到被调用)
for (int i = 0; i < 1e7; i++)
{
(x == 1) ? way1(arr) : way2(arr); //重复调用函数以获得充分多的时钟打点数
}
stop = clock(); //停止计时(从程序开始运行到被调用)
duration = ((double)(stop - start)) / CLK_TCK; //stop与start之差即为被测函数所使用的时间(时钟打点数),将其结果强制转换为double型
//再比上时间常数(上文已给出相关概念),便得出程序运行所需秒数
printf("case%d:运行时间:%.2f\n", case_n,duration);
printf(" 打点数:%.2f\n",(double)(stop - start));
}
double way1(double arr[])
{
int i;
double y = arr[0];
for (i = 1; i <= N; i++)
{
y += (arr[i] * pow(unknowN, i));
}
return y;
}
double way2(double arr[])
{
int i;
double y = arr[N];
for (i = N; i > 0; i--)
{
y = arr[i - 1] + unknowN * y;
}
return y;
}
运行结果展示:
很显然,被测函数二的时间复杂度要小于被测函数一。
由此得知,被测函数二要比被测函数一更加巧妙。
进阶版:多个被测函数的效率比较
当我们不满足于两个被测函数的比较,在这里我为大家提供进阶版的捕捉运行时间的程序,可用于两种及以上的被测函数的比较。
为了减少代码的重复性,我们需要将函数作为参数传入。
这里用到的是函数指针,用函数名来返回该函数的起始位置。
参数原型为:
ElemType(*FunctionName)(ElemType,ElemType),...)
其中,ElemType为声明(如int,float,double,struct等)
下面为大家提供一个使用模板:
//模板二
#include<stdio.h>
#include<time.h> //需要调用clock()函数
//定义全局变量
clock_t start, stop;//clock_t为time.h头文件中的一种数据类型
double duration; //定义程序运行时间为浮点型,且以秒为单位
//声明函数部分
void way1(); //被测函数一
void way2(); //被测函数二
void way3(); //被测函数三
void check(void(*way)(),int case_n);//检测程序运行时间
//主函数部分
int main()
{
//调用check()函数返回运行时间
check(way1,1);
check(way2,2);
check(way3,3);
}
//定义函数部分
void check(void(*way)(),int case_n)
{
//不在测试范围内的准备工作及处理应写在clock()函数调用的前后
start = clock(); //开始计时(从程序开始运行到被调用)
for (int i = 0; i < 1e7; i++)
{
(*way)(); //重复调用函数以获得充分多的时钟打点数
}
stop = clock(); //停止计时(从程序开始运行到被调用)
duration = ((double)(stop - start)) / CLK_TCK; //stop与start之差即为被测函数所使用的时间(时钟打点数),将其结果强制转换为double型
//再比上时间常数(上文已给出相关概念),便得出程序运行所需秒数
printf("case%d:运行时间:%f\n", case_n,duration);
printf(" 打点数:%f\n",(double)(stop - start));
}
void way1()
{
//被测函数一
}
void way2()
{
//被测函数二
}
void way3()
{
//被测函数三
}
使用模板二进行举例:
(捕捉针对解决多项式问题的两种方法的运行时间,小伙伴对此有兴趣的话,可点击下方链接阅读进行详细了解)(1条消息) 关于算法效率——通过写程序计算给定多项式在给定点X处的值_小小Vegetable的博客-CSDN博客https://blog.csdn.net/qq_75151748/article/details/128543366?spm=1001.2014.3001.5502
//模板二:解决多项式问题的两种方法
#include<stdio.h>
#include<time.h> //需要调用clock()函数
#include<math.h> //需要调用pow()函数
//定义全局变量
clock_t start, stop;//clock_t为time.h头文件中的一种数据类型
double duration; //定义程序运行时间为浮点型,且以秒为单位
#define N 10 //拟定项数的最高次N为10
#define unknowN 2.2 //拟定未知数的大小为2.2
//声明函数部分
double way1(double arr[]); //被测函数一
double way2(double arr[]); //被测函数二
void check(double(*way)(double*), double arr[], int case_n);//检测程序运行时间
//主函数部分
int main()
{
int i;
double arr[N]; //存储多项式的系数
for (i = 0; i < N; i++)
{
arr[i] = (double)i;//即arr[i]=i;
}
//调用check()函数返回运行时间
check(way1, arr,1);
check(way2, arr,2);
}
//定义函数部分
void check(double(*way)(double*),double arr[],int case_n)
{
//不在测试范围内的准备工作及处理应写在clock()函数调用的前后
start = clock(); //开始计时(从程序开始运行到被调用)
for (int i = 0; i < 1e7; i++)
{
(*way)(arr); //重复调用函数以获得充分多的时钟打点数
}
stop = clock(); //停止计时(从程序开始运行到被调用)
duration = ((double)(stop - start)) / CLK_TCK; //stop与start之差即为被测函数所使用的时间(时钟打点数),将其结果强制转换为double型
//再比上时间常数(上文已给出相关概念),便得出程序运行所需秒数
printf("case%d:运行时间:%.2f\n", case_n,duration);
printf(" 打点数:%.2f\n",(double)(stop - start));
}
double way1(double arr[])
{
int i;
double y = arr[0];
for (i = 1; i <= N; i++)
{
y += (arr[i] * pow(unknowN, i));
}
return y;
}
double way2(double arr[])
{
int i;
double y = arr[N];
for (i = N; i > 0; i--)
{
y = arr[i - 1] + unknowN * y;
}
return y;
}
运行结果展示
这里我仅检测两个被测函数的运行时间,朋友们可根据需要进行修改。
总结
以上便是对于捕捉被测函数运行时间的程序设计,虽说其过程十分简单,但还是希望能够帮到大家 。如若文章存在纰漏或错误,欢迎大家指正,谢谢!