C# 如何计算C语言中某些时间间隔的平均值#

C# 如何计算C语言中某些时间间隔的平均值#,c#,datetimepicker,timespan,C#,Datetimepicker,Timespan,我已经搜索了这个问题,但不幸的是找不到正确的答案 我想计算在10个不同的日子里花在做某事上的平均时间,我有10个datetimepicker作为开始时间,还有10个datetimepicker作为每天的结束时间(总共20个datetimepicker) 现在我想得到这10天内平均工作时间 这就是我每天计算timespan所做的,现在我不知道如何计算这些timespan 我当然想知道有没有更快捷的方法来完成这项工作 DateTime Dt1 = dateTimePicker1.Value; Dat

我已经搜索了这个问题,但不幸的是找不到正确的答案

我想计算在10个不同的日子里花在做某事上的平均时间,我有10个
datetimepicker
作为开始时间,还有10个
datetimepicker
作为每天的结束时间(总共20个
datetimepicker

现在我想得到这10天内平均工作时间

这就是我每天计算
timespan
所做的,现在我不知道如何计算这些
timespan

我当然想知道有没有更快捷的方法来完成这项工作

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()));

我想找到第1天到第10天的平均值

给定一个
IEnumerable
,您可以使用此扩展方法对其进行平均:

public static TimeSpan Average(this IEnumerable<TimeSpan> spans) => TimeSpan.FromSeconds(spans.Select(s => s.TotalSeconds).Average());
现在计算平均值:

var avgDurs = durs.Average();
PS:创建了@MattJohnson答案的
汇总版本:

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);
publicstatictimespan-Mean(这个IEnumerable源)=>TimeSpan.FromTicks(source.Aggregate((m:0L,r:0L,n:source.Count()),(tm,s)=>{
var r=tm.r+s.Ticks%tm.n;
返回值(tm.m+s.Ticks/tm.n+r/tm.n,r%tm.n,tm.n);
})(1.m);

您可以通过基于刻度数实例化新的时间跨度来找到平均值

    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); 
var time_span=new List(){new TimeSpan(24,10,0),new TimeSpan(12,0,45),new TimeSpan(23,30,0),new TimeSpan(11,34,0)};
var average=新的时间跨度(转换为64(时间跨度平均值(t=>t.Ticks));
控制台写入线(平均值);

结果
17:48:41.2500000

为了跟进NetMage完美的答案,请注意,他的
平均值
扩展方法是使用
.TotalSeconds
,它返回整数秒和分数秒的
双精度,毫秒精度。如果您从时间选择器获取值,这可能很好,但在一般情况下,这将导致精度的轻微损失

此外,
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);
}

如果你有一个数组或一个列表,而不是20个独立的变量,那会容易得多。(也不清楚为什么要格式化
TimeSpan
值,然后重新对它们进行排序。)将它们全部相加,然后除以数字。正如斯基特所说,把它们放在一个数组里,我很好奇。为什么您决定创建一个字符串只是为了再次解析它?我真的对你的动机很感兴趣,因为我一直看到这种方法,它从来都不是必需的,也不是可取的。另外,你是否保证所有的价值观对都在同一天?或者你可以有一双跨越午夜的,比如晚上11点到凌晨1点之间的两个小时?如果所有的约会时间都有相同的日期,为什么要去掉它?无论如何,你只对差异感兴趣。所以
var MyTimeSpan=myDateTime1-myDateTime2
似乎在没有
TimeOfDay
ToString()
的情况下完成了这项任务(最后一项毫无用处,但由于某些原因非常常见)。最好使用滴答声而不是秒,以免丢失更精确的任何信息。虽然在OP的情况下,可能不重要,但是来自选择器控件,如果要保留扩展方法,则希望它在各种情况下都可用。@MattJohnson添加勾号可能会在溢出时成为问题。秒是一个更好的选择。谢谢,但我得到了这个错误:
'List'不包含“Average”的定义,而最佳扩展方法重载“Queryable.Average(IQueryable)”需要一个类型为“IQueryable”的接收器
使用System.Linq添加此
@patrickhoffman-没错,但有一些方法可以用来克服这一点。虽然在这个特殊的情况下我同意你的看法谢谢,负刻度怎么办?如果它们为负值,我如何检查它们并将它们乘以-1?不需要额外的代码来处理负值。这里的所有内容都已签名。似乎是进行复杂的
聚合的好时机。顺便说一句,为什么我们使用
ICollection
而不是
IEnumerable
?为了避免由于必须调用
.Count()
而可能出现的两次枚举,我在
IEnumerable
上创建了一个
Aggregate
版本(不是所有
IEnumerable
实现
ICollection
),有趣的是
平均值
(5,10,15)与
平均值相比,秒返回的结果稍差,尽管在7
时间跨度
s的样本中,
平均值
更准确。请注意,
TimeSpan
seconds精确到毫秒。
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();