计算剩余时间

Aar*_*ith 56 c# algorithm

什么是确定完成某些事情的剩余时间的好算法?我知道有多少总行数,已经完成了多少行,我该如何估算剩余时间?

Jos*_*rke 60

为什么不?

(linesProcessed / TimeTaken) (timetaken / linesProcessed) * LinesLeft = TimeLeft

TimeLeft然后将以任何时间单位表达timeTaken.

编辑:

感谢你的评论,你应该这样:

(TimeTaken / linesProcessed) * linesLeft = timeLeft

所以我们有

(10 / 100) * 200= 20秒现在10秒过去
(20 / 100) * 200= 40秒现在剩下10秒钟我们处理100多行
(30 / 200) * 100= 15秒现在我们都看到为什么复制文件对话框从3小时跳到30分钟:-)

  • 表达式应为(TimeTaken/linesProcessed)*linesLeft (2认同)

Sco*_*pey 28

我很惊讶没有人用代码回答这个问题!

正如@JoshBerke所回答的那样,计算时间的简单方法可以编码如下:

DateTime startTime = DateTime.Now;
for (int index = 0, count = lines.Count; index < count; index++) {
    // Do the processing
    ...

    // Calculate the time remaining:
    TimeSpan timeRemaining = TimeSpan.FromTicks(DateTime.Now.Subtract(startTime).Ticks * (count - (index+1)) / (index+1));

    // Display the progress to the user
    ...
}
Run Code Online (Sandbox Code Playgroud)

这个简单的例子非常适合简单的进度计算.
但是,对于更复杂的任务,有许多方法可以改进这种计算!

例如,当您下载大文件时,下载速度可能很容易波动.要计算最准确的"ETA",一个好的算法就是只考虑过去10秒的进度.查看ETACalculator.cs以获取此算法的实现!

ETACalculator.cs来自Progression--我写的一个开源库.它为各种"进度计算"定义了一个非常易于使用的结构.它可以轻松实现报告不同类型进度的嵌套步骤.如果您担心感知性能(如@JoshBerke所建议的那样),它将对您有所帮助.


Ant*_*ean 17

确保管理感知的表现.

虽然所有进度条在测试中花费了相同的时间,但是两个特征使用户认为该过程更快,即使它不是:

  1. 进度条顺利完成
  2. 进度棒加速到最后


Cha*_*sch 13

不要复活一个死的问题,但我一直回来参考这个页面.
您可以在Stopwatch类上创建一个扩展方法,以获得可获得估计剩余时间跨度的功能.

static class StopWatchUtils
{
    /// <summary>
    /// Gets estimated time on compleation. 
    /// </summary>
    /// <param name="sw"></param>
    /// <param name="counter"></param>
    /// <param name="counterGoal"></param>
    /// <returns></returns>
    public static TimeSpan GetEta(this Stopwatch sw, int counter, int counterGoal)
    {
        /* this is based off of:
         * (TimeTaken / linesProcessed) * linesLeft=timeLeft
         * so we have
         * (10/100) * 200 = 20 Seconds now 10 seconds go past
         * (20/100) * 200 = 40 Seconds left now 10 more seconds and we process 100 more lines
         * (30/200) * 100 = 15 Seconds and now we all see why the copy file dialog jumps from 3 hours to 30 minutes :-)
         * 
         * pulled from http://stackoverflow.com/questions/473355/calculate-time-remaining/473369#473369
         */
        if (counter == 0) return TimeSpan.Zero;
        float elapsedMin = ((float)sw.ElapsedMilliseconds / 1000) / 60;
        float minLeft = (elapsedMin / counter) * (counterGoal - counter); //see comment a
        TimeSpan ret = TimeSpan.FromMinutes(minLeft);
        return ret;
    }
}
Run Code Online (Sandbox Code Playgroud)

例:

int y = 500;
Stopwatch sw = new Stopwatch();
sw.Start();
for(int x = 0 ; x < y ; x++ )
{
    //do something
    Console.WriteLine("{0} time remaining",sw.GetEta(x,y).ToString());
}
Run Code Online (Sandbox Code Playgroud)

希望它会对某些人有用.


编辑:应该注意,当每个循环花费相同的时间时,这是最准确的.
编辑2:我创建了一个扩展方法,而不是子类化.


cas*_*One 5

一般来说,您在处理过程中的任何时间点都知道三件事:

  1. 到该时间点已处理了多少单位/块/项目 (A)。
  2. 处理这些项目需要多长时间 (B)。
  3. 剩余项目的数量 (C)。

给定这些项目,剩余时间的估计(除非处理项目的时间是恒定的)将是

乙*丙/甲