簡體   English   中英

如何計算C#中某些時間跨度的平均值

[英]How to calculate average of some timespans in C#

我已經搜索了這個問題,但不幸的是找不到正確的答案。

我想計算在10天不同的時間里做某事所花費的平均時間,我每天有10個datetimepicker作為開始時間,還有10個datetimepicker作為結束時間(總共20個datetimepicker )。

現在,我想獲得這10天內花在工作上的平均時間。

這是我每天計算timespan所做的工作,現在我不知道如何計算這些timespans平均值

我當然想知道有沒有更短的方法來完成這項工作?

DateTime Dt1 = dateTimePicker1.Value;
DateTime Dt2 = dateTimePicker2.Value;
.
.
.
DateTime Dt20 = dateTimePicker20.Value;

TimeSpan Day1 = DateTime.Parse(Dt11.TimeOfDay.ToString()).Subtract(DateTime.Parse(Dt1.TimeOfDay.ToString()));
TimeSpan Day2 = DateTime.Parse(Dt12.TimeOfDay.ToString()).Subtract(DateTime.Parse(Dt2.TimeOfDay.ToString()));
.
.
.

TimeSpan Day10 = DateTime.Parse(Dt20.TimeOfDay.ToString()).Subtract(DateTime.Parse(Dt10.TimeOfDay.ToString()));

我想找到第一天到第十天的平均值

給定IEnumerable<TimeSpan>您可以使用此擴展方法將它們取平均值:

public static TimeSpan Average(this IEnumerable<TimeSpan> spans) => TimeSpan.FromSeconds(spans.Select(s => s.TotalSeconds).Average());

因此,將結果轉換為List

var durs = new List<TimeSpan>();
durs.Add(Dt11.TimeOfDay.Subtract(Dt1.TimeOfDay));
durs.Add(Dt12.TimeOfDay.Subtract(Dt2.TimeOfDay));
.
.
.

durs.Add(Dt20.TimeOfDay.Subtract(Dt10.TimeOfDay));

現在計算平均值:

var avgDurs = durs.Average();

PS:創建了@MattJohnson答案的Aggregate版本:

public static TimeSpan Mean(this IEnumerable<TimeSpan> source) => TimeSpan.FromTicks(source.Aggregate((m: 0L, r: 0L, n: source.Count()), (tm, s) => {
        var r = tm.r + s.Ticks % tm.n;
        return (tm.m + s.Ticks / tm.n + r / tm.n, r % tm.n, tm.n);
    }).m);

您可以通過基於刻度數實例化一個新的TimeSpan來找到平均值。

    var time_spans = new List<TimeSpan>() { new TimeSpan(24, 10, 0), new TimeSpan(12, 0, 45), new TimeSpan(23, 30, 0), new TimeSpan(11, 34, 0) };

    var average = new TimeSpan(Convert.ToInt64(time_spans.Average(t => t.Ticks)));

     Console.WriteLine(average); 

結果17:48:41.2500000

為了跟進NetMage的完美回答,請注意,他的Average擴展方法使用.TotalSeconds ,該方法以毫秒為單位返回整數秒和分數秒的double 如果您從時間選擇器中獲取值,那可能很好,但是在一般情況下,這將導致精度的少量損失。

此外,在處理大值時, TimeSpan.FromSeconds方法可能會溢出。 即使不求平均也可以重現:

TimeSpan.FromSeconds(TimeSpan.MaxValue.TotalSeconds)  // will throw an OverflowException

帕特里克·霍夫曼(Patrick Hofman)在評論中指出了一個好觀點,即僅從秒切換到滴答聲也可能導致溢出,因此需要另一種解決方案。

調整此答案中給出的技術,我們可以使用算術平均值方法來計算TimeSpan值集合的平均值 ,而不會損失精度,也不會發生溢出:

public static TimeSpan Mean(this ICollection<TimeSpan> source)
{
    if (source == null)
        throw new ArgumentNullException(nameof(source));

    long mean = 0L;
    long remainder = 0L;
    int n = source.Count;
    foreach (var item in source)
    {
        long ticks = item.Ticks;
        mean += ticks / n;
        remainder += ticks % n;
        mean += remainder / n;
        remainder %= n;
    }

    return TimeSpan.FromTicks(mean);
}

與其他擴展方法類似地使用它,例如:

TimeSpan average = mylistoftimespans.Mean();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM