C++ 估计C+中剩余的时间+;11
我正在编写一个进度条类,它每隔C++ 估计C+中剩余的时间+;11,c++,algorithm,c++11,C++,Algorithm,C++11,我正在编写一个进度条类,它每隔n向std::ostream输出一个更新的进度条: class progress_bar { public: progress_bar(uint64_t ticks) : _total_ticks(ticks), ticks_occured(0), _begin(std::chrono::steady_clock::now()) ... void tick() { // test to see if enough prog
n
向std::ostream
输出一个更新的进度条:
class progress_bar
{
public:
progress_bar(uint64_t ticks)
: _total_ticks(ticks), ticks_occured(0),
_begin(std::chrono::steady_clock::now())
...
void tick()
{
// test to see if enough progress has elapsed
// to warrant updating the progress bar
// that way we aren't wasting resources printing
// something that hasn't changed
if (/* should we update */)
{
...
}
}
private:
std::uint64_t _total_ticks;
std::uint64_t _ticks_occurred;
std::chrono::steady_clock::time_point _begin;
...
}
我还想输出剩余的时间。我发现了一个公式,表示剩余时间为(变量名称已更改以适合我的类):
time\u left=(所用时间/\u总刻度)*(\u总刻度-\u刻度发生)
我想用C++11新的
标题为我的课程填写的部分是剩余的时间和花费的时间
我知道我需要使用一个std::chrono::staid\u clock
,但我不知道如何将它集成到代码中。我假设测量时间的最佳方法是以纳秒为单位的std::uint64\u t
我的问题是:
中是否有一个函数可以将纳秒转换为std::string
,比如“3m12s”
我是否应该在每次更新进度条时使用std::chrono::staid\u clock::now()
,并从\u begin
中减去它来确定剩余时间
是否有更好的算法来确定剩余时间
chrono库包括用于表示持续时间的类型。您不应该将其转换为某个“已知”单位的平坦整数。当您需要一个已知的单位时,只需使用计时类型,例如“std::chrono::nanoseconds”和duration\u cast
。或者使用浮点表示法和SI比率之一创建自己的持续时间类型。例如,std::chrono::duration
。没有持续时间\u cast
或浮点持续时间四舍五入在编译时被禁止
chrono的IO功能并没有进入C++11,但您可以从中获取源代码。使用此选项,您可以忽略持续时间类型,它将打印正确的单位。我不认为有任何东西可以用分、秒等来显示时间,但这样的东西应该不会太难写
我不知道有太多的理由担心频繁地调用staddy\u clock::now()
,如果你这样问的话。我希望大多数平台都会有一个相当快的计时器来完成这类事情。不过,这确实取决于实现。显然,这给您带来了问题,因此您可能只能在if(/*我们是否应该更新*/)
块中调用stable_clock::now()
,这应该对调用频率设置合理的限制
显然,还有其他方法来估计剩余时间。例如,您可以从最后N个刻度中取平均值,而不是取迄今为止进度的平均值(这是您显示的公式所做的)。或者两者都做,取两个估计值的加权平均值
中是否有将纳秒转换为纳秒的函数
一个std::字符串,比如说“3m12s”
不,但我将在下面向您展示如何轻松地做到这一点
我应该在每次更新时使用std::chrono::stable\u clock::now()吗
我的进度条,然后从中减去它,开始确定剩下的时间
对
是否有更好的算法来确定剩余时间
对。见下文
编辑
我最初将“滴答声”误解为“时钟滴答声”,而实际上“滴答声”有工作单位,\u滴答声发生/\u总滴答声
可以解释为%job\u done。因此,我相应地更改了下面建议的进度条
我相信这个等式:
time_left = (time_taken / _total_ticks) * (_total_ticks - _ticks_occured)
这是不正确的。它未通过健全性检查:如果\u ticks\u occurrent==1
且\u total\u ticks
较大,则剩余时间
大约等于(好的,稍微少一点)所用时间
。那没有道理
我将上述等式改写为:
time_left = time_taken * (1/percent_done - 1)
在哪里
现在当完成百分比
接近零时,剩余时间
接近无穷大,当完成百分比
接近1时,剩余时间
接近0。当完成百分比
为10%时,剩余时间
为9*所用时间
。这符合我的期望,假设每个工作周期的时间成本大致呈线性
class progress_bar
{
public:
progress_bar(uint64_t ticks)
: _total_ticks(ticks), _ticks_occurred(0),
_begin(std::chrono::steady_clock::now())
// ...
{}
void tick()
{
using namespace std::chrono;
// test to see if enough progress has elapsed
// to warrant updating the progress bar
// that way we aren't wasting resources printing
// something that hasn't changed
if (/* should we update */)
{
// somehow _ticks_occurred is updated here and is not zero
duration time_taken = Clock::now() - _begin;
float percent_done = (float)_ticks_occurred/_total_ticks;
duration time_left = time_taken * static_cast<rep>(1/percent_done - 1);
minutes minutes_left = duration_cast<minutes>(time_left);
seconds seconds_left = duration_cast<seconds>(time_left - minutes_left);
}
}
private:
typedef std::chrono::steady_clock Clock;
typedef Clock::time_point time_point;
typedef Clock::duration duration;
typedef Clock::rep rep;
std::uint64_t _total_ticks;
std::uint64_t _ticks_occurred;
time_point _begin;
//...
};
实际上,稳定时钟::持续时间通常基于整数类型
将其称为代表
(表示法的缩写)。当完成百分比
大于50%时,乘以所用时间
的系数将小于1。当rep
为整数时,则转换为0。因此,这个进度条只在前50%期间表现良好,在最后50%期间预测剩余时间为0
解决这一问题的关键是使用基于浮点而非整数的duration
s进行通信。而
使这一点非常容易做到
typedef std::chrono::steady_clock Clock;
typedef Clock::time_point time_point;
typedef Clock::period period;
typedef std::chrono::duration<float, period> duration;
下面是完整的软件包,包括以下修复:
class progress_bar
{
public:
progress_bar(uint64_t ticks)
: _total_ticks(ticks), _ticks_occurred(0),
_begin(std::chrono::steady_clock::now())
// ...
{}
void tick()
{
using namespace std::chrono;
// test to see if enough progress has elapsed
// to warrant updating the progress bar
// that way we aren't wasting resources printing
// something that hasn't changed
if (/* should we update */)
{
// somehow _ticks_occurred is updated here and is not zero
duration time_taken = Clock::now() - _begin;
float percent_done = (float)_ticks_occurred/_total_ticks;
duration time_left = time_taken * (1/percent_done - 1);
minutes minutes_left = duration_cast<minutes>(time_left);
seconds seconds_left = duration_cast<seconds>(time_left - minutes_left);
std::cout << minutes_left.count() << "m " << seconds_left.count() << "s\n";
}
}
private:
typedef std::chrono::steady_clock Clock;
typedef Clock::time_point time_point;
typedef Clock::period period;
typedef std::chrono::duration<float, period> duration;
std::uint64_t _total_ticks;
std::uint64_t _ticks_occurred;
time_point _begin;
//...
};
课程进度\u栏
{
公众:
进度条(uint64标记)
:_总刻度(刻度),_刻度发生(0),
_开始(标准::时钟::稳定时钟::现在()
// ...
{}
空勾()
{
使用名称空间std::chrono;
//测试以查看是否已取得足够的进展
//为了保证更新进度条
//这样我们就不会浪费印刷资源
//一些没有改变的东西
如果(/*我们应该更新*/)
{
//不知何故,这里更新了发生的_ticks _,而不是零
持续时间=时钟::现在()-\u开始;
浮动百分比\u完成=(浮动)\u刻度\u发生/\u总刻度;
剩余持续时间=所用时间*(1/完成百分比-1);
剩余分钟数=持续时间(剩余时间);
剩余秒数=持续时间(剩余时间-剩余分钟);
std::cout“tick”的原因是表示进度,即:我有1000000个操作(tick)要完成。从我所能看出boost有一个chrono\u io
。您推荐吗
typedef Clock::duration duration;
typedef std::chrono::steady_clock Clock;
typedef Clock::time_point time_point;
typedef Clock::period period;
typedef std::chrono::duration<float, period> duration;
duration time_left = time_taken * (1/percent_done - 1);
class progress_bar
{
public:
progress_bar(uint64_t ticks)
: _total_ticks(ticks), _ticks_occurred(0),
_begin(std::chrono::steady_clock::now())
// ...
{}
void tick()
{
using namespace std::chrono;
// test to see if enough progress has elapsed
// to warrant updating the progress bar
// that way we aren't wasting resources printing
// something that hasn't changed
if (/* should we update */)
{
// somehow _ticks_occurred is updated here and is not zero
duration time_taken = Clock::now() - _begin;
float percent_done = (float)_ticks_occurred/_total_ticks;
duration time_left = time_taken * (1/percent_done - 1);
minutes minutes_left = duration_cast<minutes>(time_left);
seconds seconds_left = duration_cast<seconds>(time_left - minutes_left);
std::cout << minutes_left.count() << "m " << seconds_left.count() << "s\n";
}
}
private:
typedef std::chrono::steady_clock Clock;
typedef Clock::time_point time_point;
typedef Clock::period period;
typedef std::chrono::duration<float, period> duration;
std::uint64_t _total_ticks;
std::uint64_t _ticks_occurred;
time_point _begin;
//...
};