假设您要计算剩余的下载时间,并且您拥有所需的所有信息,即:文件大小,dl'ed大小,左侧大小,已用时间,瞬间dl速度等等。 你会如何计算剩余的dl时间?
当然,直接的方式是:尺寸左/瞬间dl速度,或:(经过的时间/尺寸)*尺寸左。 只有第一个会受到瞬时速度偏差的影响,后者不能很好地适应速度变化。
必须是一些更明智的方法,对吧?查看您目前使用uTorrent下载的盗版软件和音乐。很容易注意到它比以前提到的简单计算更有用。实际上,我注意到有时当dl速度下降时,剩余的时间也会下降一段时间,直到它重新调整为止。
答案 0 :(得分:12)
好吧,正如你所说,使用绝对当前的下载速度并不是一个好方法,因为它往往会波动。然而,像整体平均水平这样的东西也不是一个好主意,因为那里也可能存在很大的波动。
考虑我是否与其他9个人同时开始下载文件。我只获得正常速度的10%,但在文件的中途,另外9个完成。现在我的速度是我开始时的10倍。我最初的10%速度不应该是“剩下多少时间?”的一个因素。再计算。
就个人而言,我可能会在过去30秒左右取平均值,并使用它。这应该根据最近的速度进行计算,而不会大幅波动。 30秒可能不是正确的数量,需要一些实验来计算出好的数量。
另一种选择是设置一种“波动阈值”,在速度变化超过该阈值之前,您不会重新计算。例如(随机数,同样需要实验),您可以将阈值设置为10%。然后,如果您以100kb / s的速度下载,则在下载速度变为低于90kb / s或110kb / s之前,不会重新计算剩余时间。如果发生其中一个更改,则重新计算时间并设置新阈值。
答案 1 :(得分:10)
您可以使用平均算法,其中旧值线性衰减。如果S_n是时间n的速度而A_ {n-1}是时间n-1的平均值,那么定义你的平均速度如下。
A_1 = S_1
A_2 =(S_1 + S_2)/ 2
A_n = S_n /(n-1)+ A_ {n-1}(1-1 /(n-1))
在英语中,这意味着测量过去的时间越长,重要性就越小,因为它的重要性已经衰退。
将此与常规平均算法进行比较: A_n = S_n / n + A_ {n-1}(1-1 / n)
你也可以让它几何衰减,这会对最近的速度造成很大影响: A_n = S_n / 2 + A_ {n-1} / 2
如果速度是4,3,5,6那么
A_4 = 4.5(简单平均值)
A_4 = 4.75(线性衰减)
A_4 = 5.125(几何衰减)
请注意$n+1
(不是$n
)是由于PHP的数组被零索引而导致的当前数据点数。要匹配上述示例集n == $n+1
或n-1 == $n
<?php
$s = [4,3,5,6];
// average
$a = [];
for ($n = 0; $n < count($s); ++$n)
{
if ($n == 0)
$a[$n] = $s[$n];
else
{
// $n+1 = number of data points so far
$weight = 1/($n+1);
$a[$n] = $s[$n] * $weight + $a[$n-1] * (1 - $weight);
}
}
var_dump($a);
// linear decay
$a = [];
for ($n = 0; $n < count($s); ++$n)
{
if ($n == 0)
$a[$n] = $s[$n];
elseif ($n == 1)
$a[$n] = ($s[$n] + $s[$n-1]) / 2;
else
{
// $n = number of data points so far - 1
$weight = 1/($n);
$a[$n] = $s[$n] * $weight + $a[$n-1] * (1 - $weight);
}
}
var_dump($a);
// geometric decay
$a = [];
for ($n = 0; $n < count($s); ++$n)
{
if ($n == 0)
$a[$n] = $s[$n];
else
{
$weight = 1/2;
$a[$n] = $s[$n] * $weight + $a[$n-1] * (1 - $weight);
}
}
var_dump($a);
输出
array (size=4)
0 => int 4
1 => float 3.5
2 => float 4
3 => float 4.5
array (size=4)
0 => int 4
1 => float 3.5
2 => float 4.25
3 => float 4.8333333333333
array (size=4)
0 => int 4
1 => float 3.5
2 => float 4.25
3 => float 5.125
答案 2 :(得分:7)
显而易见的方法是介于两者之间,你需要一个下载速度的“移动平均线”。
答案 3 :(得分:2)
我认为这只是一种平均算法。它的平均速度只有几秒钟。
答案 4 :(得分:1)
您还可以做的是跟踪您的平均速度并显示其计算结果。
答案 5 :(得分:0)
编辑:这是我最后的建议,我尝试了它,它提供了非常令人满意的结果:
我有一个零初始化数组,每个下载速度在0 - 500 kB / s之间(如果你期望这样的速度,可能会更高),步长为1 kB / s。 我暂时采样下载速度(每秒都是一个很好的间隔),并将相应的数组项增加一。 现在我知道每个速度下载文件花了多少秒。所有这些值的总和是经过的时间(以秒为单位)。这些值的总和乘以相应的速度是到目前为止下载的大小。 如果我取数组中每个值与经过时间之间的比率,假设速度变化模式稳定,我可以形成一个公式来预测每个尺寸所需的时间。在这种情况下,此大小是剩余的大小。我就是做这个的: 我将每个数组项值的总和乘以相应的速度(索引)并除以经过的时间。然后我将该值除以左边的大小,这就是剩下的时间。
需要几秒钟的稳定时间,然后安然无恙地工作。
请注意,这是一个“复杂”的平均值,因此丢弃旧值(移动平均值)的方法可能会进一步改善它。
答案 6 :(得分:0)
对于任何有兴趣的人,我在C#中编写了一个名为Progression的开源库,它具有“移动平均”实现:ETACalculator.cs。
Progression库定义了一种易于使用的结构,用于报告多种类型的进度。它还可以轻松处理嵌套进度,以实现非常流畅的进度报告。