捕捉程序运行时间——clock()函数的原理及其用法详解

目录

前言

基础版:两个被测函数的效率比较

进阶版:多个被测函数的效率比较

总结


前言

当你对于一个问题存在多种解法时,是否难以弄清哪一种方法更加巧妙?

本篇文章来教大家通过使用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博客icon-default.png?t=MBR7https://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博客icon-default.png?t=MBR7https://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;
}

 运行结果展示

 

 这里我仅检测两个被测函数的运行时间,朋友们可根据需要进行修改。

总结

以上便是对于捕捉被测函数运行时间的程序设计,虽说其过程十分简单,但还是希望能够帮到大家 。如若文章存在纰漏或错误,欢迎大家指正,谢谢!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值