當前位置:首頁 » 編程軟體 » 編程時間精度

編程時間精度

發布時間: 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 22:10:29 瀏覽:747
php微信授權登錄 發布:2025-02-07 22:10:27 瀏覽:377
怎樣編程時鍾 發布:2025-02-07 21:59:38 瀏覽:561
誇克編程 發布:2025-02-07 21:43:43 瀏覽:528
電源450適合哪些配置 發布:2025-02-07 21:25:24 瀏覽:431
微信密碼一般要多少位以上 發布:2025-02-07 21:24:19 瀏覽:879
sqldecimal轉換 發布:2025-02-07 21:17:50 瀏覽:659
鋼管查詢源碼 發布:2025-02-07 21:15:25 瀏覽:427
濱州伺服器租賃地址 發布:2025-02-07 21:13:41 瀏覽:439
thinkphp刪除資料庫數據 發布:2025-02-07 21:12:03 瀏覽:946