第二章 2.1 前期估算与实践编码验证(随机数,clock,time)

单对于算法本身来说,我们最关注的层面是效率性。

运行时间(效率)计算方法:

①前期估算:一般总是存在几种不同的方法来解决问题,我们总是想尽早除去那些不好的算法思想,尽管确定哪个程序更快的最好方法是将它们编码并运行。

但是如果都这样做,无疑会额外消耗太多精力与时间,所以前期估算非常重要。

同时,估算能让我们尽快的确定算法瓶颈所在。

②实际编码:通过前期估算获得了某些结论,那么在具体的计算机系统上,我们就需要实际编码并运行,来验证估算的结论是否正确,以及是否满足我们的需求。

——————————————————————————————————
前期估算法则:
① 为了简化分析,不存在特定的时间单位,一条语句占用1个时间单位。
②从内部(深层)向外展开。
③ FOR循环法则,即循环内语句运行时间乘以循环次数。
④顺序语句法则,将各个语句的运行时间求和。
⑤IF S1 /ELSE  S2 法则,将S1和S2中运行时间更长的那个作为总运行时间。

实际编码:

①数据准备工作:我们需要预先准备一些数据,用来验证几种不同的解决方法哪个更快;在数据量很小的情况下,不同的算法很难体现差别,而稍微大一些的数据量如果用人工输入的方式,显然很难完成。

我们可以使用C语言的文件读写功能,来创造包含大量数据的文件,比如1万个数据,10万个数据,100万个数据。

为了简化模拟,假设每个数据都是整数,并且它们之间的数值大小无规律(使用随机数)。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define randmax 10
#define randmin 0

int main(void)
{
 int roll;
 srand((unsigned int)time(NULL));
 for (int i=0; i<randmax;i++)
   { 
     roll =  rand()%(randmax - randmin +1) + randmin;
     printf("随机数字为:%d\n",roll);
   } 
 return 0;
}

要使用随机数,必须包含stdlib.h头文件,固定种子发生器srand采用的是伪随机,改进成srand(time(NULL))后,每次执行可达到真正的随机效果。

产生一个区间在[randmax,randmin]的随机数,公式为:

rand()%(randmax - randmin +1) + randmin


②计时方式:使用C语言的时间库函数time.h 

#include <stdio.h>
#include <time.h>
#define MAXLOOP 5000000
int main(void)
{
 clock_t start, end;
 time_t  begin, finish;
 start = clock();
 printf("开始clock时间为: %ld\n",start);
 begin = time(NULL);
 for (int i=0; i<MAXLOOP; i++)
     {
         
       for (int j=0; j<1000; j++)
       {
                ;                                     //空语句
       }
     }
 
 end = clock();
 printf("结束clock时间为: %ld\n",end);
 finish = time(NULL);
 printf("循环%d次,消耗时间为:%f秒\n",MAXLOOP, (double)(end -  start)/CLOCKS_PER_SEC);
printf("begin的日历时间为:%ld\n",begin);
printf("finish的日历时间为:%ld\n",finish);
printf("日历时间总消耗为:%f秒\n",difftime(finish,begin));
return 0;
}

要使用时间,必须包含time.h头文件,另外值得注意的是,要区分clock_t时间和time_t时间。

很多教材语焉不详,含糊的说它们为%d,或者%ld格式,更有说clock()函数返回的是毫秒,这是完全错误的!

clock_t表明的是时钟周期的次数,是操作系统在运行该程序时,从0开始消耗掉的时钟周期次数。

因此要转为实际的秒数,必须用以下公式:

(double)(end -  start)/CLOCKS_PER_SEC

在这里加上double格式,是为了保证有足够的精度。

time_t表明的是日历时间,是从1970年开始,到当前操作系统(右下角)时间的总秒数。

为了保证可移植性,time_t不能直接相减(相减可能获得正确值),而是用difftime()函数来进行转换。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值