当前位置:首页 » 编程软件 » 编程时间精度

编程时间精度

发布时间: 2022-07-16 13:13:41

1. C语言编程如何实现较精确的时间控制

用程序本身监控时间意义是不大的,因为程序运行在一个系统资源不固定的系统中
cpu,内存,调度对我们来说是不可见的,每个运行在系统中的程序cpu,内存占用都是有抖动的,可能在某个时间段系统资源紧张,没有调度到你的程序,它就慢了,这个难说

2. 请教VC++高手 如何输出高精度时间差

VC时间控制函数就这几类找了一个总结文章

一般时控函数

VC程序员都会利用Windows的WM—TIMER消息映射来进行简单的时间控制:1.调用函数SetTimer()设置定时间隔,如SetTimer(0,200,NULL)即为设置200毫秒的时间间隔;2.在应用程序中增加定时响应函数OnTimer(),并在该函数中添加响应的处理语句,用来完成时间到时的操作。这种定时方法是非常简单的,但其定时功能如同Sleep()函数的延时功能一样,精度较低,只可以用来实现诸如位图的动态显示等对定时精度要求不高的情况,而在精度要求较高的条件下,这种方法应避免采用。

精度时控函数

在要求误差不大于1毫秒的情况下,可以采用GetTickCount()函数,该函数的返回值是DWORD型,表示以毫秒为单位的计算机启动后经历的时间间隔。使用下面的编程语句,可以实现50毫秒的精确定时,其误差小于1毫秒。

DWORD dwStart, dwStop;

// 起始值和终止值

dwStop = GetTickCount();

while(TRUE)

{

dwStart = dwStop;

// 上一次的终止值变成新的起始值

// 此处添加相应控制语句

do

{

dwStop = GetTickCount();

} while(dwStop - 50 < dwStart);

}

高精度时控函数

对于一般的实时控制,使用GetTickCount()函数就可以满足精度要求,但要进一步提高计时精度,就要采用QueryPerformanceFrequency()函数和QueryPerformanceCounter()函数。这两个函数是VC提供的仅供Windows 9X使用的高精度时间函数,并要求计算机从硬件上支持高精度计时器。QueryPerformanceFrequency()函数和QueryPerformanceCounter()函数的原型为:

BOOL QueryPerformanceFrequency(LARGE—INTEGER *lpFrequency);

BOOL QueryPerformanceCounter(LARGE—INTEGER *lpCount) ;

数据类型LARGE—INTEGER既可以是一个作为8字节长的整型数,也可以是作为两个4字节长的整型数的联合结构,其具体用法根据编译器是否支持64位而定。该类型的定义如下:

typedef union —LARGE—INTEGER

{

struct

{

DWORD LowPart; // 4字节整型数

LONG HighPart; // 4字节整型数

};

LONGLONG QuadPart;

// 8字节整型数

} LARGE—INTEGER;

在进行计时之前,应该先调用QueryPerformanceFrequency()函数获得机器内部计时器的时钟频率。笔者在主频为266、300、333的三种PentiumⅡ机器上使用该函数,得到的时钟频率都是1193180Hz。接着,笔者在需要严格计时的事件发生之前和发生之后分别调用QueryPerformanceCounter()函数,利用两次获得的计数之差和时钟频率,就可以计算出事件经历的精确时间。以下程序是用来测试函数Sleep(100)的精确持续时间。

LARGE—INTEGER litmp;

LONGLONG QPart1,QPart2;

double dfMinus, dfFreq, dfTim;

QueryPerformanceFrequency(&litmp);

// 获得计数器的时钟频率

dfFreq = (double)litmp.QuadPart;

QueryPerformanceCounter(&litmp);

// 获得初始值

QPart1 = litmp.QuadPart;

Sleep(100) ;

QueryPerformanceCounter(&litmp);

// 获得终止值

QPart2 = litmp.QuadPart;

dfMinus = (double)(QPart2 - QPart1);

dfTim = dfMinus / dfFreq;

// 获得对应的时间值

执行上面程序,得到的结果为dfTim=0.097143767076216(秒)。细心的读者会发现,每次执行的结果都不一样,存在一定的差别,这是由于Sleep()自身的误差所致。

本文介绍了三种定时或计时的实现方法,读者可以根据自己的实际情况进行选择,以达到程序的定时和计时功能。以上程序均在VC 6.0、Windows 98环境下调试通过。

3. 给定年月日 怎样用C语言编程计算2个日期之间的时间天数

1970 年以后的时间,可以用 time.h 里的函数计算。时间精度为秒。按题目要求,输出时间单位用天。程序如下:
#include <stdio.h>
#include <time.h>
time_t YMD_hhmmss_2_s70(int Y, int M, int D, int hh, int mm, int ss){
struct tm *target_tm;
time_t tt;
time (&tt);
target_tm=localtime(&tt);
target_tm->tm_year = Y - 1900;
target_tm->tm_mon= M - 1;
target_tm->tm_mday = D;
target_tm->tm_hour = hh; // hour
target_tm->tm_min = mm;
target_tm->tm_sec = ss;
tt = mktime(target_tm); // from tm to time_t (s)
return tt;
}
int main()
{
int y1,m1,d1,y2,m2,d2;
time_t t1,t2;
int dt;
printf("input y1 m1 d1: ");
scanf("%d %d %d",&y1,&m1,&d1);
printf("\ninput y2 m2 d2: ");
scanf("%d %d %d",&y2,&m2,&d2);
t1 = YMD_hhmmss_2_s70(y1,m1,d1,0,0,0);
t2 = YMD_hhmmss_2_s70(y2,m2,d2,0,0,0);
dt = (t2-t1)/(24*3600);
printf("\ndt=%d\n",dt);
return 0;
}
这里未包含日期的合法性判断。
1970 年以前 要另写程序。某年的日子是当年的第几天可用下面函数得出:
int YMD_2_JD(int Y, int M, int D){
const short MonthDay[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int JD,i;
JD=D;
for (i=0;i<M;i++) JD+=MonthDay[i];
if (((Y%4==0)&&(Y%100!=0)||(Y%400==0)) && (M>2)) JD++;
return JD;
}
整年的天数,涉及闰年的判断:
某年是否闰年,用 (Y%4==0)&&(Y%100!=0)||(Y%400==0) 判断。闰年366天,平年365天。 有了这些,写程序不难。
未考虑公元前的年月日计算。

4. VC++编程中 如何获取当前时间(精确到毫秒)

1、直接利用Pentium CPU内部时间戳进行计时的高精度计时手段。
2、在 Intel Pentium以上级别的CPU中,有一个称为“时间戳(Time Stamp)”的部件,它以64位无符号整型数的格式,记录了自CPU上电以来所经过的时钟周期数。由于目前的CPU主频都非常高,因此这个部件可以达到纳秒级的计时精度。
3、因为RDTSC不被C++的内嵌汇编器直接支持,所以要用_emit伪指令直接嵌入该指令的机器码形式0X0F、0X31,如下:
inline unsigned __int64 GetCycleCount()
{
__asm _emit 0x0F
__asm _emit 0x31
}
4、在需要计数器的场合,可以像使用普通的Win32 API一样,调用两次GetCycleCount函数,比较两个返回值的差,像这样:
unsigned long t;
t = (unsigned long)GetCycleCount();
//Do Something time-intensive ...
t -= (unsigned long)GetCycleCount();

5. 如何对可编程电源实现精确的时间控制

方法/步骤

1:到官方下载驱动NI vsia 驱动安装包

2:安装驱动,注意,默认并不安装Visa 库,但是我们开发程序需要用到它,请选择安装Visa,其他选择下一步,直至安装完成。安装结束后可以在安装目录下找到开发所用到的头文件和库文件。(注:安装结束后需要重启电脑)。

3:仪器连接

Visa支持Ethernet, GPIB, GPIB-VXI, VXI, PXI, or 串口连接. 程控仪器66311可用的控制端口有GPIB和串口两种,为了可靠性连接及传输的高速度,通常选用GPIB连接。另外,GPIB卡有PCI内置(较便宜),还有USB外置型(较贵),按照电脑--> GPIB卡-->GPIB线-->仪器连接。 并参照66311B手册,设定GPIB地址为5 (出厂默认设置为5) 。

可编程任意电源就是某些功能或参数可以通过计算机软件编程控制的电源。比如设置输出电压是多少,最大输出电流是多少,超过这个值则不能正常供电等等。例如,当超过最大输出电压的时候为恒流输出,当超过最大输出电流的时候,电源就变成了稳压源等等。

“可编程”的意思是电源内部主要功能通过上位机设定状态字实现可控,大部分的电源是通过串口连接的。可通过通讯规约,设定“最大电流、最大电压、最大功率、实际电压”等等。可编程任意电源的主要指标是编程时间,编程精度,编程分辨率等。

6. 定时器/计数器精度问题 在定时的时候 感觉编程的循序会影响时间精度吧执行指令的时候不也是有机器周期

你好、我来为你解答:
#include <reg51.h>
unsigned char i;
void main()
{
TMOD=0x10;
TH1=0x3c;
TL1=0xb0;
EA=1;
ET1=1;
TR1=1;

while(1)
{
if(i==20)
{
i=0;
//下面写你要处理的的其他程序,你只要了定时1s。
}
}
}

void a(void) interrupt 3
{
unsigned char i;
TH1=0x3c;
TL1=0xb0;
i++;
}

12Mhz的51单片机,经过12分频后为1MHz,则一个指令周期为1/1Mhz = 1us.
则定时50ms为 0xffff - 0x3cb0,即65535 - 15535 = 50000us = 50ms,则20次的定时:20×50ms=1s。

明白了吗?怪简单的问题……

祝你顺利哦!

7. VC中如何获取当前时间(精度达到毫秒级)

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

在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 函数需要链接多媒体库winmm.lib,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位无符号整数所能表达的最大数字是1.8×10^19,在我的Celeron 800上可以计时大约700年(书中说可以在200MHz的Pentium上计时117年,这个数字不知道是怎么得出来的,与我的计算有出入)。无论如何,我们大可不必关心溢出的问题。

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

//Timer1.cpp 使用了RDTSC指令的Timer类//KTimer类的定义可以参见《Windows图形编程》P15
//编译行:CL Timer1.cpp /link USER32.lib
#include <stdio.h>
#include "KTimer.h"
main()
{
unsigned t;
KTimer timer;
timer.Start();
Sleep(1000);
t = timer.Stop();
printf("Lasting Time: %d\n",t);
}

//Timer2.cpp 使用了timeGetTime函数
//需包含<mmsys.h>,但由于Windows头文件错综复杂的关系
//简单包含<windows.h>比较偷懒:)
//编译行:CL timer2.cpp /link winmm.lib
#include <windows.h>
#include <stdio.h>

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));
}

//Timer3.cpp 使用了QueryPerformanceCounter函数
//编译行:CL timer3.cpp /link KERNEl32.lib
#include <windows.h>
#include <stdio.h>

main()
{
LARGE_INTEGER t1, t2, tc;
QueryPerformanceFrequency(&tc);
printf("Frequency: %u\n", tc.QuadPart);
QueryPerformanceCounter(&t1);
Sleep(1000);
QueryPerformanceCounter(&t2);
printf("Begin Time: %u\n", t1.QuadPart);
printf("End Time: %u\n", t2.QuadPart);
printf("Lasting Time: %u\n",( t2.QuadPart- t1.QuadPart));
}

////////////////////////////////////////////////
//以上三个示例程序都是测试1秒钟休眠所耗费的时间
file://测/试环境:Celeron 800MHz / 256M SDRAM
// Windows 2000 Professional SP2
// Microsoft Visual C++ 6.0 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

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

8. 单片机编三位秒表程序,要求精度1%秒,所编程序达不到要求精度怎么解决

这个问题我只能说个思路,定时器运行时是按微秒运行的,所以,理论上说要想达到1%秒的精度应该是没问题的,但是,根据程序结构的不同一定会有误差的,所以,我看你的程序“65536-10000”的赋值方式,就知道会有误差的,我的方法是经过24小时以上的计时后与标准时间(比如网络时间)比较,找出比较规律的误差值,而后修改赋值量,经过几次修改,可以达到相当高的精度;换言之,要想精确延时10Ms,定时器赋值可能是9998、也可能是10004(这只是比如说),你试试吧,祝成功。

热点内容
夸克编程 发布:2025-02-07 21:43:43 浏览:527
电源450适合哪些配置 发布:2025-02-07 21:25:24 浏览:430
微信密码一般要多少位以上 发布:2025-02-07 21:24:19 浏览:878
sqldecimal转换 发布:2025-02-07 21:17:50 浏览:658
钢管查询源码 发布:2025-02-07 21:15:25 浏览:425
滨州服务器租赁地址 发布:2025-02-07 21:13:41 浏览:438
thinkphp删除数据库数据 发布:2025-02-07 21:12:03 浏览:945
安卓智能手机哪个更便宜 发布:2025-02-07 21:10:24 浏览:144
织梦数据库连接 发布:2025-02-07 21:09:32 浏览:353
缓解情绪解压的句子 发布:2025-02-07 21:04:23 浏览:535