如何用C语言编写一个显示时间的函数,要求时间显示精度到毫秒级别。

如何用C语言编写一个显示时间的函数,要求时间显示精度到毫秒级别。,第1张

#include <cstdio>

#include <ctime>

using namespace std;

/ run this program using the console pauser or add your own getch, system("pause") or input loop /

void printTime() {

  struct tm t;   //tm结构指针

time_t now;  //声明time_t类型变量

time(&now);      //获取系统日期和时间

localtime_s(&t, &now);   //获取当地日期和时间

   //格式化输出本地时间

printf("年-月-日-时-分-秒:%d-%d-%d %d:%d:%d\n", ttm_year + 1900, ttm_mon + 1, ttm_mday, ttm_hour, ttm_min, ttm_sec);

}

int main(int argc, char argv) {

printTime();

}

clock()返回的是CPU时钟计时单元,而CLOCKS_PER_SEC它用来表示一秒钟会有多少个时钟计时单元,所以正确的运行时间是(finish-start)/CLOCKS_PER_SEC,这样就能得到执行了多少秒,要得到毫秒的话再乘以10000,微妙再乘以10000

对关注性能的程序开发人员而言,一个好的计时部件既是益友,也是良师。计时器既可以作为程序组件帮助程序员精确的控制程序进程,又是一件有力的调试武器,在有经验的程序员手里可以尽快的确定程序的性能瓶颈,或者对不同的算法作出有说服力的性能比较。

在Windows平台下,常用的计时器有两种,一种是timeGetTime多媒体计时器,它可以提供毫秒级的计时。但这个精度对很多应用场合而言还是太粗糙了。另一种是QueryPerformanceCount计数器,随系统的不同可以提供微秒级的计数。对于实时图形处理、多媒体数据流处理、或者实时系统构造的程序员,善用QueryPerformanceCount/QueryPerformanceFrequency是一项基本功。

本文要介绍的,是另一种直接利用Pentium CPU内部时间戳进行计时的高精度计时手段。以下讨论主要得益于《Windows图形编程》一书,第 15页-17页,有兴趣的读者可以直接参考该书。关于RDTSC指令的详细讨论,可以参考Intel产品手册。本文仅仅作抛砖之用。

在 Intel Pentium以上级别的CPU中,有一个称为“时间戳(Time Stamp)”的部件,它以64位无符号整型数的格式,记录了自CPU上电以来所经过的时钟周期数。由于目前的CPU主频都非常高,因此这个部件可以达到纳秒级的计时精度。这个精确性是上述两种方法所无法比拟的。

在Pentium以上的CPU中,提供了一条机器指令RDTSC(Read Time Stamp Counter)来读取这个时间戳的数字,并将其保存在EDX:EAX寄存器对中。由于EDX:EAX寄存器对恰好是Win32平台下C++语言保存函数返回值的寄存器,所以我们可以把这条指令看成是一个普通的函数调用。像这样:

inline unsigned __int64 GetCycleCount()

{

__asm RDTSC

}

但是不行,因为RDTSC不被C++的内嵌汇编器直接支持,所以我们要用_emit伪指令直接嵌入该指令的机器码形式0X0F、0X31,如下:

inline unsigned __int64 GetCycleCount()

{

__asm _emit 0x0F

__asm _emit 0x31

}

以后在需要计数器的场合,可以像使用普通的Win32 API一样,调用两次GetCycleCount函数,比较两个返回值的差,像这样:

unsigned long t;

t = (unsigned long)GetCycleCount();

//Do Something time-intensive

t -= (unsigned long)GetCycleCount();

《Windows图形编程》第15页编写了一个类,把这个计数器封装起来。有兴趣的读者可以去参考那个类的代码。作者为了更精确的定时,做了一点小小的改进,把执行RDTSC指令的时间,通过连续两次调用GetCycleCount函数计算出来并保存了起来,以后每次计时结束后,都从实际得到的计数中减掉这一小段时间,以得到更准确的计时数字。但我个人觉得这一点点改进意义不大。在我的机器上实测,这条指令大概花掉了几十到100多个周期,在 Celeron 800MHz的机器上,这不过是十分之一微秒的时间。对大多数应用来说,这点时间完全可以忽略不计;而对那些确实要精确到纳秒数量级的应用来说,这个补偿也过于粗糙了。

这个方法的优点是:

1高精度。可以直接达到纳秒级的计时精度(在1GHz的CPU上每个时钟周期就是一纳秒),这是其他计时方法所难以企及的。

2 成本低。timeGetTime 函数需要链接多媒体库winmmlib,QueryPerformance 函数根据MSDN的说明,需要硬件的支持(虽然我还没有见过不支持的机器)和KERNEL库的支持,所以二者都只能在Windows平台下使用(关于DOS平台下的高精度计时问题,可以参考《图形程序开发人员指南》,里面有关于控制定时器8253的详细说明)。但RDTSC指令是一条CPU指令,凡是i386平台下Pentium以上的机器均支持,甚至没有平台的限制(我相信i386版本UNIX和Linux下这个方法同样适用,但没有条件试验),而且函数调用的开销是最小的。

3 具有和CPU主频直接对应的速率关系。一个计数相当于1/(CPU主频Hz数)秒,这样只要知道了CPU的主频,可以直接计算出时间。这和 QueryPerformanceCount不同,后者需要通过QueryPerformanceFrequency获取当前计数器每秒的计数次数才能换算成时间。

这个方法的缺点是:

1现有的C/C++编译器多数不直接支持使用RDTSC指令,需要用直接嵌入机器码的方式编程,比较麻烦。

2数据抖动比较厉害。其实对任何计量手段而言,精度和稳定性永远是一对矛盾。如果用低精度的timeGetTime来计时,基本上每次计时的结果都是相同的;而RDTSC指令每次结果都不一样,经常有几百甚至上千的差距。这是这种方法高精度本身固有的矛盾。

关于这个方法计时的最大长度,我们可以简单的用下列公式计算:

自CPU上电以来的秒数 = RDTSC读出的周期数 / CPU主频速率(Hz)

64位无符号整数所能表达的最大数字是18×10^19,在我的Celeron 800上可以计时大约700年(书中说可以在200MHz的Pentium上计时117年,这个数字不知道是怎么得出来的,与我的计算有出入)。无论如何,我们大可不必关心溢出的问题。

下面是几个小例子,简要比较了三种计时方法的用法与精度

//Timer1cpp 使用了RDTSC指令的Timer类//KTimer类的定义可以参见《Windows图形编程》P15

//编译行:CL Timer1cpp /link USER32lib

#include &ltstdioh>

#include "KTimerh"

main()

{

unsigned t;

KTimer timer;

timerStart();

Sleep(1000);

t = timerStop();

printf("Lasting Time: %d\n",t);

}

//Timer2cpp 使用了timeGetTime函数

//需包含&ltmmsysh>,但由于Windows头文件错综复杂的关系

//简单包含&ltwindowsh>比较偷懒:)

//编译行:CL timer2cpp /link winmmlib

#include &ltwindowsh>

#include &ltstdioh>

main()

{

DWORD t1, t2;

t1 = timeGetTime();

Sleep(1000);

t2 = timeGetTime();

printf("Begin Time: %u\n", t1);

printf("End Time: %u\n", t2);

printf("Lasting Time: %u\n",(t2-t1));

}

//Timer3cpp 使用了QueryPerformanceCounter函数

//编译行:CL timer3cpp /link KERNEl32lib

#include &ltwindowsh>

#include &ltstdioh>

main()

{

LARGE_INTEGER t1, t2, tc;

QueryPerformanceFrequency(&tc);

printf("Frequency: %u\n", tcQuadPart);

QueryPerformanceCounter(&t1);

Sleep(1000);

QueryPerformanceCounter(&t2);

printf("Begin Time: %u\n", t1QuadPart);

printf("End Time: %u\n", t2QuadPart);

printf("Lasting Time: %u\n",( t2QuadPart- t1QuadPart));

}

////////////////////////////////////////////////

//以上三个示例程序都是测试1秒钟休眠所耗费的时间

file://测/试环境:Celeron 800MHz / 256M SDRAM

// Windows 2000 Professional SP2

// Microsoft Visual C++ 60 SP5

////////////////////////////////////////////////

以下是Timer1的运行结果,使用的是高精度的RDTSC指令

Lasting Time: 804586872

以下是Timer2的运行结果,使用的是最粗糙的timeGetTime API

Begin Time: 20254254

End Time: 20255255

Lasting Time: 1001

以下是Timer3的运行结果,使用的是QueryPerformanceCount API

Frequency: 3579545

Begin Time: 3804729124

End Time: 3808298836

Lasting Time: 3569712

古人说,触类旁通。从一本介绍图形编程的书上得到一个如此有用的实时处理知识,我感到非常高兴。有美不敢自专,希望大家和我一样喜欢这个轻便有效的计时器。

datetime包含毫秒,要格式化输出,用fff

DateTime t = DateTimeNow;

ConsoleWriteLine(tToString("yyyy-MM-dd hh:mm:ss fff"));

注:mysql里面的datetime类型的精确度是可以到1/ 10 ^ 6 秒的,某些客户端(如navicat for mysql)的显示经常只能看到精确到秒,其实是设计表的时候的配置问题。

扩展资料:

mysql中DateTime和Timestamp

DateTime

1、8个字节储存(8 bytes storage)

2、实际格式储存(Just stores what you have stored and retrieves the same thing which you have stored)

3、与时区无关(It has nothing to deal with the TIMEZONE and Conversion)

4、存储的时间范围为:'1000-01-01 00:00:00000000' 到 '9999-12-31 23:59:59999999'

Timestamp

1、4个字节储存(Time stamp value is stored in 4 bytes)

2、值以UTC格式保存( it stores the number of milliseconds)

3、时区转化 ,存储时对当前的时区进行转换,检索时再转换回当前的时区。

4、存储的时间范围为:'1970-01-01 00:00:01000000' 到 '2038-01-19 03:14:07999999'

几条语句,没有循环,毫秒级有点大了

#include <windowsh>

#include <stdioh>

 

int main()

{

    DWORD start,

stop;

    start =

GetTickCount();

    Sleep(3000);

    stop =

GetTickCount();

    printf("time: %lld ms\n",

stop - start);

    return 0;

}

~

以上就是关于如何用C语言编写一个显示时间的函数,要求时间显示精度到毫秒级别。全部的内容,包括:如何用C语言编写一个显示时间的函数,要求时间显示精度到毫秒级别。、C++计算一个程序运行时间,精确到毫秒、VC中如何获取当前时间(精度达到毫秒级)等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/9606407.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-30
下一篇2023-04-30

发表评论

登录后才能评论

评论列表(0条)

    保存