信息发布软件,b2b软件,广告发布软件
标题: 一个不能有误差的高精度算法C++绝对是一个能信任的能手 [打印本页]
作者: 群发软件 时间: 2017-6-22 23:07
标题: 一个不能有误差的高精度算法C++绝对是一个能信任的能手
//C++高精度实现计算程序运行时间
#include <iostream>
#include <windows.h>
using namespace std;
void Test()//测试程序
{
for(int i=0; i<1000; i++)
{
for(int j=0; j<100; j++)
{
printf("%d,%d\n",i,j);
}
}
}
int main(void)
{
LARGE_INTEGER BegainTime ;
LARGE_INTEGER EndTime ;
LARGE_INTEGER Frequency ;
QueryPerformanceFrequency(&Frequency);
QueryPerformanceCounter(&BegainTime) ;
//要测试的代码放在这里
Test();
QueryPerformanceCounter(&EndTime);
//输出运行时间(单位:s)
cout << "运行时间(单位:s):" <<(double)( EndTime.QuadPart - BegainTime.QuadPart )/ Frequency.QuadPart <<endl;
system("pause") ;
return 0 ;
}
附 vc计算高精度时间差
面线框里的代码便可实现计算精度达到微秒级的时间差:
------------------------------------------------------------------------------------
LARGE_INTEGER litmp;
LONGLONG QPart1,Qpart2;
double dfMinus,dfFreq,dfTime;
//获得计时器的时钟频率
QueryPerformanceFrequency(&litmp);
dfFreq = (double)litmp.QuadPart;
QueryPerformanceCounter(&litmp);
Qpart1 = litmp.QuadPart; //开始计时
Block1(); //工作模块 函数等,根据自己需要添加。
QueryPerformanceCounter(&litmp);
Qpart2 = litmp.QuadPart; //终止计时
dfMinus = (double)(QPart2 - QPart1);//计算计数器值
dfTime = dfMinus / dfFreq;//获得对应时间,单位为秒 你可以乘1000000精确到毫秒级(us)
--------------------------------------------------------------------------------------
在一些计算机硬件系统中,包含有高精度运行计数器(high-resolution performance
counter),利用它可以获得高精度定时间隔,其精度与CPU的时钟频率有关。
1、首先调用QueryPerformanceFrequency函数取得高精度运行计数器的频率f。单位是每秒多少次(n/s),此数
一般很大。
2、在需要定时的代码的两端分别调用QueryPerformanceCounter以取得高精度运行计数器的数值n1,n2。两次数
值的差值通过f换算成时间间隔,t=(n2-n1)/f。
下面举一个例子来演示这种方法的使用及它的精确度。
在VC 6.0 下用MFC建立一个对话框工程,取名为HightTimer.在对话框面板中控件的布局如下图:
其中包含两个静态文本框,两个编辑框和两个按纽。上面和下面位置的编辑框的ID分别为IDC_E_TEST和IDC_E_ACT
UAL,通过MFC ClassWizard添加的成员变量也分别对应为DWORD m_dwTest和DWORD m_dwAct.
“退出”按纽的ID为IDOK,“开始测试”按纽ID为IDC_B_TEST,用MFC
ClassWizard添加此按纽的单击消息处理函数如下:
void CHightTimerDlg::OnBTest()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE); //取输入的测试时间值到与编辑框相关联的成员变量m_dwTest中
LARGE_INTEGER frequence;//LARGE_INTEGER是一个联合,其中LOWPART为低32位,HIGHPART为高32位,
//两者构成一个结构,而QuadPart是其中的64位符号整数,为LongLong类型
if(!QueryPerformanceFrequency( &frequence)) //取高精度运行计数器的频率,若硬件不支持则返回FALSE
MessageBox("Your computer hardware doesn't support the high-resolution performance counter",
"Not Support", MB_ICONEXCLAMATION | MB_OK);
LARGE_INTEGER test, ret;
test.QuadPart = frequence.QuadPart * m_dwTest / 1000000;
//通过频率换算微秒数到对应的数量(与CPU时钟有关),1秒=1000000微秒
//test 中存储着m_dwTest毫秒所需的次数
ret = MySleep( test ); //调用此函数开始延时,返回实际花销的数量
m_dwAct = (DWORD)(1000000 * ret.QuadPart / frequence.QuadPart ); //换算到微秒数
UpdateData(FALSE); //显示到对话框面板
}
其中上面调用的MySleep函数如下:
LARGE_INTEGER CHightTimerDlg::MySleep(LARGE_INTEGER Interval)
///////////////////////////////////////////////////////////////////////////////////////////////////
//////////
// 功能:执行实际的延时功能
// 参数:Interval 参数为需要执行的延时与时间有关的数量
// 返回值:返回此函数执行后实际所用的时间有关的数量
///////////////////////////////////////////////////////////////////////////////////////////////////
////////
{
LARGE_INTEGER privious, current, Elapse;
QueryPerformanceCounter( &privious );
current = privious;
while( current.QuadPart - privious.QuadPart < Interval.QuadPart )
QueryPerformanceCounter( ¤t );
Elapse.QuadPart = current.QuadPart - privious.QuadPart;
return Elapse;
}
注:别忘了在头文件中为此函数添加函数声明。
至此,可以编译和执行此工程了,当测试时间超过3微秒时,准确度已经非常高了,此时机器执行本身延时函数代码的时间对需要延时的时间影响很小了。
上面的函数由于演示测试的需要,没有在函数级封装,下面给出的函数基本上可以以全局函数的形式照搬到别的
程序中。
BOOL MySleep(DWORD dwInterval)
///////////////////////////////////////////////////////////////////////////////////////////////////
//////////
// 功能:执行微秒级的延时功能
// 参数:Interval 参数为需要的延时数(单位:微秒)
// 返回值:若计算机硬件不支持此功能,返回FALSE,若函数执行成功,返回TRUE
///////////////////////////////////////////////////////////////////////////////////////////////////
////////
{
BOOL bNormal = TRUE;
LARGE_INTEGER frequence, privious, current, interval;
if(!QueryPerformanceFrequency( &frequence))
{
::MessageBox(NULL, "Your computer hardware doesn't support the high-resolution performance
counter",
"Not Support", MB_ICONEXCLAMATION | MB_OK); //或其它的提示信息
return FALSE;
}
interval.QuadPart = frequence.QuadPart * dwInterval / 1000000;
bNormal = bNormal && QueryPerformanceCounter( &privious );
current = privious;
while( current.QuadPart - privious.QuadPart < interval.QuadPart )
bNormal = bNormal && QueryPerformanceCounter( ¤t );
return bNormal;
}
需要指出的是,由于在此函数中的代码很多,机器在执行这些代码所花费的时间也很长,所以在需要几个微秒的
延时时,会影响精度。实际上,读者在熟悉这种方法后,只要使用QueryPerformanceFrequency和QueryPerforman
ceCounter这两个函数就能按实际需要写出自己的延时代码了。
给你个类吧,我在用呢
// Elapsed.h: interface for the CElapsed class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_ELAPSED_H__4A992E21_8B47_11D6_B1B2_FFFCE130B010__INCLUDED_)
#define AFX_ELAPSED_H__4A992E21_8B47_11D6_B1B2_FFFCE130B010__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CElapsed
{
private:
int Initialized;
__int64 Frequency;
__int64 BeginTime;
public:
BOOL Avaliable();
double End();
BOOL Begin();
CElapsed();
virtual ~CElapsed();
};
#endif // !defined(AFX_ELAPSED_H__4A992E21_8B47_11D6_B1B2_FFFCE130B010__INCLUDED_)
// Elapsed.cpp: implementation of the CElapsed class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
//#include "myimage.h"
#include "Elapsed.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CElapsed::CElapsed()
{
Initialized=QueryPerformanceFrequency((LARGE_INTEGER *)&Frequency);
}
CElapsed::~CElapsed()
{
}
BOOL CElapsed::Begin()
{
if(!Initialized)
return 0;
return QueryPerformanceCounter((LARGE_INTEGER *)&BeginTime);
}
double CElapsed::End()
{
if(!Initialized)
return 0;
__int64 endtime;
QueryPerformanceCounter((LARGE_INTEGER *)&endtime);
__int64 elapsed=endtime-BeginTime;
return (double)elapsed/(double)Frequency;
}
BOOL CElapsed::Avaliable()
{
return Initialized;
}
解决一个问题通常有多种方法, 我们总想找到最高效的,所以需要对比不同算法执行所用的时间。可惜的是,C++中提供的方法一般只能精确到毫秒级。
提供一种更加精确的方法。编写一个函数,可以在C++中这样写:
__declspec (naked) unsigned __int64 GetCpuCycle( void )
{
_asm
{
rdtsc
ret
}
}
RDTSC的返回值存放在EDX EAX中, EDX为高32位,EAX为低32位。这里的 RDTSC 指令( Read Time Stamp Counter ), 获得CPU的高精度时间戳。
这样以来我们就可以在随处获得当前的CPU自上电以来的时间周期数了:
unsigned __int64 iCpuCycle = GetCpuCycle();
根据这个数字我们可以计算出上电以来所经历的时间( 秒s ):
second = iCpuCycle / CPU主频率( HZ );
1GHZ = 1,000 MHZ = 1,000,000 KHZ = 1,000,000,000 HZ;
获取两次作差就可以得到运行的时间了。其实没必要换算成时间,关注差值就行了。
PS:
可以放心一个unsigned __int64 不会溢出 - - 可以计算一下你的CPU能保存多少年的时间。。
根据这一方法有几个好处: 一是精度高,二是函数调用开销最小,三是平台限制小,四是具有和CPU主频相对应的直接关系。。。 但是由于精度高,得到的数字浮动比较大。。
作者: q117971371 时间: 2017-6-22 23:12
真是好,真的是免费的呀。谢谢,祝你生意兴隆、财源滚滚!
作者: shenyeben 时间: 2017-6-26 16:03
棒棒哒!先让他们设计一款宝贝详情,速度快不说,客服态度也好,本来不相信这些网上的东西,没想到还真特么的不错
作者: w8899 时间: 2017-6-28 04:47
精湛!没到一分钟就把我这问题解决了!我自己研究了大半天都没弄懂!不错!
作者: xiaoyaoyao001 时间: 2017-6-29 21:18
,客服很有耐心,我说了很多的要求都一一的帮我改了,有需要还会再来找你们设计的
作者: yangjiang1 时间: 2017-7-2 04:29
,下载好几天才完成.太值了.慢慢研究.
作者: 694012770 时间: 2017-7-4 17:07
及时做出评价,系统默认好评!
作者: niubttt 时间: 2017-7-4 18:35
很好,服务也好,耐心细致,下次还会来的
作者: 枯干枯干 时间: 2017-7-11 21:44
很好,服务也好,耐心细致,下次还会来的
作者: niyaoz1 时间: 2017-7-13 02:15
沟通问题已经解决,客服晨曦服务态度比较好。就是线上沟通,有些困难。希望可以尽快完善。合作愉快
作者: xiaozhu168 时间: 2017-7-13 05:49
漂亮,高端大气上档次,大爱,服务态度也好,值得推荐的设计团队,希望生意会因此好一点!
作者: dccmdy 时间: 2017-7-13 06:26
家,技术不错,售后服务也很好。
作者: weipinzongmeng 时间: 2017-7-17 17:44
,一般般
作者: nble002 时间: 2017-7-19 07:58
不知该说些什么。。。。。。就是谢谢
作者: c19900420 时间: 2017-7-22 00:28
很到位,做的速度也还行,技术服务配合也很到位。价格还算公道。好评吧
欢迎光临 信息发布软件,b2b软件,广告发布软件 (http://postbbs.com/) |
Powered by Discuz! X3.2 |