c++中 时间差的计算

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++中 时间差的计算相关的知识,希望对你有一定的参考价值。

了解的帮忙:

C++ 中 我希望 从2007年1月1日这天开始 计算到当前系统时间的时间差
就是从那时开始一共到现在 有多少天了
请问该如何实现 `` 希望可以把代码讲明白点`
谢谢`

送30分咯

file: day.cc
=======================================================

#include <cstdio>
#include <ctime>

int main(void)

struct tm currentTime, beforeTime;
time_t now,before;
int rs;

beforeTime.tm_year=2007-1900;
beforeTime.tm_mon=1-1;
beforeTime.tm_mday=1;
beforeTime.tm_hour=0;
beforeTime.tm_min=0;
beforeTime.tm_sec=1;
beforeTime.tm_isdst=-1;

before=mktime(&beforeTime);

time(&now);
rs=static_cast<int> ( difftime(now,before)/(24*60*60) );

printf("Current Time is: %s",asctime(localtime(&now)));
printf("Difference from 01/01/2007 is: %d days\n",rs);
return 0;


Compile , Link with VC6.0 and Run
========================================================

G:\workspace\c_cpp\test\question>cl /GX /TP day.cc
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
Copyright (C) Microsoft Corp 1984-1998. All rights reserved.

day.cc
Microsoft (R) Incremental Linker Version 6.00.8168
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

/out:day.exe
day.obj

G:\workspace\c_cpp\test\question>day
Current Time is: Tue Dec 25 19:54:50 2007
Difference from 01/01/2007 is: 358 days
参考技术A #include<iostream.h>
void main()

int h1,h2,m1,m2,s1,s2,N,M,T;
char cont;
bool quit=true;
while (quit)

cout<<"input the first time:";
for(cin>>h1>>m1>>s1;(h1>=24 || m1>=60 || s1>=60);cin>>h1>>m1>>s1)//判断输入时间是否非法
cout<<"error!Please input again!"<<endl;
cout<<"The first time is:"<<h1<<":"<<m1<<":"<<s1<<endl;
cout<<"input the second time:";
for(cin>>h2>>m2>>s2;(h2>=24 || m2>=60 || s2>=60);cin>>h2>>m2>>s2)//同上
cout<<"error!Please input again!"<<endl;
cout<<"The second time is:"<<h2<<":"<<m2<<":"<<s2<<endl;
N=h1*3600+m1*60+s1;
M=h2*3600+m1*60+s2;
if(N>M)T=N-M;
else T=M-N;//求时间差
cout<<"The temp is:"<<T<<" s"<<endl;
cout<<"Do you want to continue?(y or n)"<<endl;
cin>>cont;
if(cont=='n') quit=false;//问是否循环


这是求两个时间的时间差 你稍稍修改下就行
方法很笨 希望高手能告诉个简单点的学习下~~

在 C++ 中计算移动平均线

【中文标题】在 C++ 中计算移动平均线【英文标题】:Calculating moving average in C++ 【发布时间】:2012-01-21 03:03:46 【问题描述】:

我正在尝试计算信号的移动平均值。信号值 ( a double ) 随机更新。 我正在寻找一种有效的方法来实时计算时间窗口内的时间加权平均值。我可以自己做,但比我想象的更具挑战性。

我在互联网上找到的大多数资源都在计算周期性信号的移动平均值,但我的更新是随机时间的。

有人知道这方面的好资源吗?

谢谢

【问题讨论】:

到目前为止你得到了什么?你怎么知道它是低效的? 这在您的上下文中可能有用也可能没用,但是 指数 移动平均线可能是固定窗口移动平均线的合适替代方案。递归计算非常容易。 如果您的数据类型是整数,计算固定窗口移动平均值也非常便宜 (O(1))。 由于权重函数未知(不同的时间间隔),如果不保留最后 N 个值并每次计算加权平均值,您将无法即时计算移动平均值。 指数移动平均线相关:***.com/questions/1023860/… 【参考方案1】:

注意:显然这不是解决这个问题的方法。将其留在这里以供参考,以了解这种方法有什么问题。检查 cmets。

已更新 - 基于 Oli 的评论...但不确定他所说的不稳定性。

根据值使用“到达时间”的排序图。到达一个值后,将到达时间连同它的值一起添加到排序地图并更新移动平均值。

警告这是伪代码:

SortedMapType< int, double > timeValueMap;

void onArrival(double value)

    timeValueMap.insert( (int)time(NULL), value);


//for example this runs every 10 seconds and the moving window is 120 seconds long
void recalcRunningAverage()

    // you know that the oldest thing in the list is 
    // going to be 129.9999 seconds old
    int expireTime = (int)time(NULL) - 120;
    int removeFromTotal = 0;
    MapIterType i;
    for( i = timeValueMap.begin();
    (i->first < expireTime || i != end) ; ++i )
    
    

    // NOW REMOVE PAIRS TO LEFT OF i

    // Below needs to apply your time-weighting to the remaining values
    runningTotal = calculateRunningTotal(timeValueMap); 
    average = runningTotal/timeValueMap.size();

那里...没有完全充实,但你明白了。

注意事项: 正如我所说,上面是伪代码。您需要选择合适的地图。 不要在迭代时删除这些对,因为您将使迭代器无效并且必须重新开始。 另请参阅下面 Oli 的评论。

【讨论】:

这不起作用:它没有考虑每个值存在的窗口长度的比例。此外,这种先加后减的方法只对整数类型稳定,对浮点数无效。 @OliCharlesworth - 抱歉,我错过了描述中的一些关键点(双重和时间加权)。我会更新。谢谢。 时间加权是另一个问题。但这不是我要说的。我指的是当一个新值第一次进入时间窗口时,它对平均值的贡献是最小的。它的贡献会继续增加,直到进入一个新值。 Shirely 他现在可以简单地将他需要的任何算法应用于剩余的值吗?他有他需要的所有信息……价值的数量、价值和到达时间。 我不认为你可以将总数除以事件数,你必须除以时间跨度。希望calculateRunningTotal 中应用的权重能够解释这一点。【参考方案2】:

如果近似值没问题并且样本之间有最短时间,您可以尝试超级采样。有一个数组,表示比最小值更短的均匀间隔时间间隔,并在每个时间段存储接收到的最新样本。间隔越短,平均值越接近真实值。周期不应超过最小值的一半,否则可能会丢失样本。

【讨论】:

【参考方案3】:

诀窍如下:您可以通过void update(int time, float value) 随机获取更新。但是,您还需要跟踪更新何时脱离时间窗口,因此您设置了一个“警报”,该“警报”在time + N 上调用,它会删除以前的更新曾经在计算中再次考虑过。

如果这种情况实时发生,您可以请求操作系统调用 void drop_off_oldest_update(int time) 方法,以便在 time + N 处调用

如果这是模拟,您无法从操作系统获得帮助,您需要手动进行。在模拟中,您将使用作为参数提供的时间调用方法(与实时不相关)。然而,一个合理的假设是保证调用是这样的,时间参数正在增加。在这种情况下,您需要维护警报时间值的排序列表,并且对于每个updateread 调用,您检查时间参数是否大于警报列表的头部。虽然您执行与警报相关的处理(丢弃最旧的更新)更大,但移除磁头并再次检查,直到处理给定时间之前的所有警报。然后进行更新调用。

到目前为止,我一直认为你会为实际计算做什么是显而易见的,但我会详细说明以防万一。我假设您有一个方法 float read (int time) 用于读取值。目标是使此调用尽可能高效。所以你在每次调用read 方法时计算移动平均值。相反,您预先计算上次更新或上次警报时的值,并通过几个浮点运算“调整”该值,以考虑自上次更新以来的时间流逝。 (即除了可能处理堆积的警报列表之外的恒定数量的操作)。

希望这很清楚——这应该是一个非常简单且非常高效的算法。

进一步优化:剩下的问题之一是如果在时间窗口内发生大量更新,那么很长一段时间内既没有读取也没有更新,然后读取或更新随之而来。在这种情况下,上述算法在增量更新每个正在下降的更新的值方面效率低下。这不是必需的,因为我们只关心超出时间窗口的最后一次更新,所以如果有一种方法可以有效地删除所有较旧的更新,那将会有所帮助。

为此,我们可以修改算法,对更新进行二分搜索,以找到时间窗口之前的最新更新。如果需要“删除”的更新相对较少,则可以增量更新每个删除的更新的值。但如果有许多更新需要删除,那么可以在删除旧更新后从头开始重新计算值。

关于增量计算的附录:我应该在句子中澄清我所说的增量计算的意思通过几个浮点运算“调整”这个值以解释时间的流逝自上次更新以来。初始非增量计算:

开始
sum = 0; 
updates_in_window = /* set of all updates within window */; 
prior_update' = /* most recent update prior to window with timestamp tweaked to window beginning */; 
relevant_updates = /* union of prior_update' and updates_in_window */,  

然后按时间递增的顺序遍历relevant_updates

for each update EXCEPT last  
    sum += update.value * time_to_next_update; 
,  

最后

moving_average = (sum + last_update * time_since_last_update) / window_length;

现在,如果恰好有一个更新从窗口中掉下来,但没有新的更新到来,请将sum 调整为:

sum -= prior_update'.value * time_to_next_update + first_update_in_last_window.value * time_from_first_update_to_new_window_beginning;

(注意它是prior_update',它的时间戳被修改为最后一个窗口的开始)。如果恰好有一个更新进入窗口但没有新的更新脱落,将sum调整为:

sum += previously_most_recent_update.value * corresponding_time_to_next_update. 

应该很明显,这是一个粗略的草图,但希望它显示了您如何保持平均值,以便在摊销的基础上每次更新操作 O(1)。但请注意上一段中的进一步优化。另请注意旧答案中提到的稳定性问题,这意味着浮点错误可能会在大量此类增量操作中累积,从而与对应用程序很重要的完整计算结果存在差异。

【讨论】:

【参考方案4】:
#include <map>
#include <iostream>

// Sample - the type of a single sample
// Date - the type of a time notation
// DateDiff - the type of difference of two Dates    
template <class Sample, class Date, class DateDiff = Date>
class TWMA 
private:
  typedef std::map<Date, Sample> qType;
  const DateDiff windowSize; // The time width of the sampling window
  qType samples; // A set of sample/date pairs
  Sample average; // The answer

public:

  // windowSize - The time width of the sampling window
  TWMA(const DateDiff& windowSize) : windowSize(windowSize), average(0) 

  // Call this each time you receive a sample
  void
  Update(const Sample& sample, const Date& now) 
    // First throw away all old data
    Date then(now - windowSize);
    samples.erase(samples.begin(), samples.upper_bound(then));

    // Next add new data
    samples[now] = sample;

    // Compute average: note: this could move to Average(), depending upon
    // precise user requirements.
    Sample sum = Sample();
    for(typename qType::iterator it = samples.begin();
        it != samples.end();
        ++it) 
      DateDiff duration(it->first - then);
      sum += duration * it->second;
      then = it->first;
    
    average = sum / windowSize;
  

  // Call this when you need the answer.
  const Sample& Average()  return average; 

;

int main () 
  TWMA<double, int> samples(10);

  samples.Update(1, 1);
  std::cout << samples.Average() << "\n"; // 1
  samples.Update(1, 2);
  std::cout << samples.Average() << "\n"; // 1
  samples.Update(1, 3);
  std::cout << samples.Average() << "\n"; // 1
  samples.Update(10, 20);
  std::cout << samples.Average() << "\n"; // 10
  samples.Update(0, 25);
  std::cout << samples.Average() << "\n"; // 5
  samples.Update(0, 30);
  std::cout << samples.Average() << "\n"; // 0

【讨论】:

感谢您的回答。需要它来实际“缓存”总平均值的一项改进,这样我们就不会一直循环。此外,这可能是一个小问题,但使用双端队列或列表来存储值不是更有效,因为我们假设更新将以正确的顺序出现。插入会比在地图中更快。 是的,您可以缓存sum 的值。减去您擦除的样本的值,添加您插入的样本的值。另外,是的,deque&lt;pair&lt;Sample,Date&gt;&gt; 可能更有效。我选择map 是为了可读性和调用map::upper_bound 的方便性。与往常一样,首先编写正确的代码,然后分析和衡量增量变化。

以上是关于c++中 时间差的计算的主要内容,如果未能解决你的问题,请参考以下文章

计算 C++ 中函数的执行时间(Visual Studio 2010)

在 C++ 中计算移动平均线

如何在 C++ 中计算下周六之前的秒数?

使用chrono c++库计算时间戳的差异

C++中用time_t保存在文件中的时间与现在的系统时间时间差计算

C++ 中五子棋游戏的计算机播放器 [关闭]