C# 如何在DateTime值数组中查找平均日期/时间
如果我有一个日期时间值数组:C# 如何在DateTime值数组中查找平均日期/时间,c#,datetime,average,C#,Datetime,Average,如果我有一个日期时间值数组: List<DateTime> arrayDateTimes; 平均值应为: 2003-May-21 18:00:00 若你们有一个大的列表,你们可以使用下面的方法 var count = dates.Count; double temp = 0D; for (int i = 0; i < count; i++) { temp += dates[i].Ticks / (double)count; } var average = new D
List<DateTime> arrayDateTimes;
平均值应为:
2003-May-21 18:00:00
若你们有一个大的列表,你们可以使用下面的方法
var count = dates.Count;
double temp = 0D;
for (int i = 0; i < count; i++)
{
temp += dates[i].Ticks / (double)count;
}
var average = new DateTime((long)temp);
var count=dates.count;
双温=0D;
for(int i=0;i
课程计划
{
静态void Main(字符串[]参数)
{
列表日期=新列表(){
新日期时间(2003,5,21,16,0,0),新日期时间(2003,5,21,17,0,0),
新日期时间(2003,5,21,18,0,0),新日期时间(2003,5,21,19,0,0),
新日期时间(2003,5,21,20,0,0),新日期时间(2003,5,21,16,0,0),
新日期时间(2003,5,21,17,0,0),新日期时间(2003,5,21,18,0,0),
新日期时间(2003,5,21,19,0,0),新日期时间(2003,5,21,20,0,0),
新日期时间(2003,5,21,16,0,0),新日期时间(2003,5,21,17,0,0),
新日期时间(2003,5,21,18,0,0),新日期时间(2003,5,21,19,0,0),
新日期时间(2003,5,21,20,0,0),新日期时间(2003,5,21,16,0,0),
新日期时间(2003,5,21,18,0,0),新日期时间(2003,5,21,19,0,0),
新日期时间(2003,5,21,20,0,0),新日期时间(2003,5,21,16,0,0),
新日期时间(2003,5,21,18,0,0),新日期时间(2003,5,21,19,0,0),
新日期时间(2003,5,21,20,0,0),新日期时间(2003,5,21,16,0,0),
新日期时间(2003,5,21,18,0,0),新日期时间(2003,5,21,19,0,0),
新日期时间(2003,5,21,20,0,0),新日期时间(2003,5,21,16,0,0),
新日期时间(2003,5,21,18,0,0),新日期时间(2003,5,21,19,0,0),
新日期时间(2003,5,21,20,0,0),新日期时间(2003,5,21,16,0,0),
新日期时间(2003,5,21,18,0,0),新日期时间(2003,5,21,19,0,0),
新日期时间(2003,5,21,20,0,0),新日期时间(2003,5,21,16,0,0),
新日期时间(2003,5,21,18,0,0),新日期时间(2003,5,21,19,0,0),
新日期时间(2003,5,21,20,0,0),新日期时间(2003,5,21,16,0,0),
};
var averageDate=dates.Average();
控制台写入线(平均日期);
Console.ReadKey();
}
}
公共静态类扩展
{
公共静态长期平均值(此IEnumerable longs)
{
long count=longs.count();
长均值=0;
foreach(以长为单位的var val)
{
平均值+=val/计数;
}
回归均值;
}
公共静态日期时间平均值(此IEnumerable dates)
{
返回新的日期时间(dates.Select(x=>x.Ticks.Average());
}
}
这不应溢出,但它假定日期时间是按顺序排列的:
var first = dates.First().Ticks;
var average = new DateTime(first + (long) dates.Average(d => d.Ticks - first));
事实上,上面的内容确实充斥着更大的列表和更大的差距。我想你可以用几秒钟来扩大射程。(同样,先排序)此外,这可能不是最有效的方法,但对我来说,仍然相对较快地完成了1000万次约会。不确定它是否更容易阅读,YYMV
var first = dates.First();
var average = first.AddSeconds(dates.Average(d => (d - first).TotalSeconds));
来源:摘自并修改了一点
List<DateTime> dates = new List<DateTime>();
//Add dates
for (int i = 1; i <= 28; i++) //days
for (int j = 1; j <= 12; j++) //month
for (int k = 1900; k <= 2013; k++) //year
dates.Add(new DateTime(k, j, i, 1, 2, 3)); //over 38000 dates
输出时间:1956-Dec-29 06:09:25
最初,文章中的代码如下:
double totalSec = 0;
for (int i = 0; i < dates.Count; i++)
{
TimeSpan ts = dates[i].Subtract(DateTime.MinValue);
totalSec += ts.TotalSeconds;
}
double averageSec = totalSec / dates.Count;
DateTime averageDateTime = DateTime.MinValue.AddSeconds(averageSec);
double totalSec=0;
for(int i=0;i
代码:
var count = dates.Count;
double temp = 0D;
for (int i = 0; i < count; i++)
{
temp += dates[i].Ticks / (double)count;
}
var average = new DateTime((long)temp);
答案是正确的。它通过进行增量平均来防止溢出
然而,这是错误的,因为它不能处理溢出和他对公式的误解
平均值=(x1+x2+…xN)/N非(x1/N+x2/N+…xN/N)
这是相同的公式。这是使用分配属性的简单数学:
2(x + y) = 2x + 2y
平均公式与总和乘以1/N或将每个X乘以1/N并相加相同
1/n (x1 + x2 + ... xn)
通过分配属性,它变成:
x1/n + x2/n + ... xn/n
这里有一些
他的答案也不好,因为它不能像公认的答案那样防止溢出
我可能会对他的回答发表评论,但我没有足够的声誉。使用双秒而不是长刻度将避免在任何实际输入上溢出-这里的扩展方法
public static DateTime Average(this IEnumerable<DateTime> elements)
{
if (elements == null)
{
throw new ArgumentNullException(nameof(elements));
}
var enumerated = elements.ToArray(); //so we don't iterate a potentially one-use stream multiple times.
if (!enumerated.Any())
{
throw new ArgumentException("Average of 0 elements is undefined", nameof(elements));
}
var epoch = enumerated.Min();
var secondsSinceEpoch = enumerated.Select(d => (d - epoch).TotalSeconds).ToArray();
var n = secondsSinceEpoch.LongLength;
double totalSecondsSinceEpoch = secondsSinceEpoch.Sum();
return epoch.AddSeconds(totalSecondsSinceEpoch / n);
}
[TestMethod]
public void HugeDateAverage_DoesntThrow()
{
var epoch = new DateTime(1900,1,1);
try
{
var dates = Enumerable.Range(1, 1_000_000_000)
.Select(i => epoch.AddSeconds(i));
var result = dates.Average();
}
catch (Exception ex)
{
Assert.Fail();
}
}
publicstaticdatetime平均值(这是IEnumerable元素)
{
if(elements==null)
{
抛出新的ArgumentNullException(nameof(elements));
}
var enumerated=elements.ToArray();//因此我们不会多次迭代一个潜在的单用途流。
如果(!enumerated.Any())
{
抛出新ArgumentException(“0个元素的平均值未定义”,nameof(elements));
}
var epoch=enumerated.Min();
var secondsSinceEpoch=enumerated.Select(d=>(d-epoch).TotalSeconds.ToArray();
var n=secondsSinceEpoch.LongLength;
double TotalSecondSinceEpoch=secondSinceEpoch.Sum();
返回epoch.AddSeconds(totalSecondsSinceEpoch/n);
}
[测试方法]
公共空间被包围平均值不超过()
{
var epoch=新日期时间(1900,1,1);
尝试
{
变量日期=可枚举范围(1,1\u 000\u 000)
.选择(i=>epoch.AddSeconds(i));
var result=dates.Average();
}
捕获(例外情况除外)
{
Assert.Fail();
}
}
如果您真的想要退化,您可以检测溢出并在一半元素上递归,注意奇数N的情况。这是未经测试的,但想法如下:
//NOT FOR ACTUAL USE - JUST FOR FUN
public static DateTime AverageHuge(this IEnumerable<DateTime> elements)
{
if (elements == null)
{
throw new ArgumentNullException(nameof(elements));
}
var enumerated = elements.ToArray(); //so we don't iterate a potentially one-use stream multiple times.
if (!enumerated.Any())
{
throw new ArgumentException("Average of 0 elements is undefined", nameof(elements));
}
var epoch = enumerated.Min();
var secondsSinceEpoch = enumerated.Select(d => (d - epoch).TotalSeconds).ToArray();
var n = secondsSinceEpoch.LongLength;
if (n > int.MaxValue)
{
//we could actually support more by coding Take+Skip with long arguments.
throw new NotSupportedException($"only int.MaxValue elements supported");
}
try
{
double totalSecondsSinceEpoch = secondsSinceEpoch.Sum(); //if this throws, we'll have to break the problem up
//otherwise we're done.
return epoch.AddSeconds(totalSecondsSinceEpoch / n);
}
catch (OverflowException) { } //fall out of this catch first so we don't throw from a catch block
//Overengineering to support large lists whose totals would be too big for a double.
//recursively get the average of each half of values.
int pivot = (int)n / 2;
var avgOfAvgs = (new []
{
enumerated.Take(pivot).AverageHuge(),
enumerated.Skip(pivot).Take(pivot).AverageHuge()
}).AverageHuge();
if (pivot * 2 == n)
{ // we had an even number of elements so we're done.
return avgOfAvgs;
}
else
{ //we had an odd number of elements and omitted the last one.
//it affects the average by 1/Nth its difference from the average (could be negative)
var adjust = ((enumerated.Last() - avgOfAvgs).TotalSeconds) / n;
return avgOfAvgs.AddSeconds(adjust);
}
}
//不是为了实际使用-只是为了好玩
公共静态日期时间平均值巨大(此为IEnumerable元素)
{
if(elements==null)
{
抛出新的ArgumentNullException(nameof(elements));
}
var enumerated=elements.ToArray();//因此我们不会多次迭代一个潜在的单用途流。
如果(!
1/n (x1 + x2 + ... xn)
x1/n + x2/n + ... xn/n
public static DateTime Average(this IEnumerable<DateTime> elements)
{
if (elements == null)
{
throw new ArgumentNullException(nameof(elements));
}
var enumerated = elements.ToArray(); //so we don't iterate a potentially one-use stream multiple times.
if (!enumerated.Any())
{
throw new ArgumentException("Average of 0 elements is undefined", nameof(elements));
}
var epoch = enumerated.Min();
var secondsSinceEpoch = enumerated.Select(d => (d - epoch).TotalSeconds).ToArray();
var n = secondsSinceEpoch.LongLength;
double totalSecondsSinceEpoch = secondsSinceEpoch.Sum();
return epoch.AddSeconds(totalSecondsSinceEpoch / n);
}
[TestMethod]
public void HugeDateAverage_DoesntThrow()
{
var epoch = new DateTime(1900,1,1);
try
{
var dates = Enumerable.Range(1, 1_000_000_000)
.Select(i => epoch.AddSeconds(i));
var result = dates.Average();
}
catch (Exception ex)
{
Assert.Fail();
}
}
//NOT FOR ACTUAL USE - JUST FOR FUN
public static DateTime AverageHuge(this IEnumerable<DateTime> elements)
{
if (elements == null)
{
throw new ArgumentNullException(nameof(elements));
}
var enumerated = elements.ToArray(); //so we don't iterate a potentially one-use stream multiple times.
if (!enumerated.Any())
{
throw new ArgumentException("Average of 0 elements is undefined", nameof(elements));
}
var epoch = enumerated.Min();
var secondsSinceEpoch = enumerated.Select(d => (d - epoch).TotalSeconds).ToArray();
var n = secondsSinceEpoch.LongLength;
if (n > int.MaxValue)
{
//we could actually support more by coding Take+Skip with long arguments.
throw new NotSupportedException($"only int.MaxValue elements supported");
}
try
{
double totalSecondsSinceEpoch = secondsSinceEpoch.Sum(); //if this throws, we'll have to break the problem up
//otherwise we're done.
return epoch.AddSeconds(totalSecondsSinceEpoch / n);
}
catch (OverflowException) { } //fall out of this catch first so we don't throw from a catch block
//Overengineering to support large lists whose totals would be too big for a double.
//recursively get the average of each half of values.
int pivot = (int)n / 2;
var avgOfAvgs = (new []
{
enumerated.Take(pivot).AverageHuge(),
enumerated.Skip(pivot).Take(pivot).AverageHuge()
}).AverageHuge();
if (pivot * 2 == n)
{ // we had an even number of elements so we're done.
return avgOfAvgs;
}
else
{ //we had an odd number of elements and omitted the last one.
//it affects the average by 1/Nth its difference from the average (could be negative)
var adjust = ((enumerated.Last() - avgOfAvgs).TotalSeconds) / n;
return avgOfAvgs.AddSeconds(adjust);
}
}