也许是一个无用的问题:
public static double Average<TSource>(
this IEnumerable<TSource> source,
Func<TSource, int> selector
)
上述方法抛出的异常之一也是 OverflowException:序列中元素的总和大于Int64.MaxValue。
我假设这个例外的原因是使用变量计算平均值的总和 小号 类型 long
?但由于返回值属于类型 double
,为什么没有设计师选择制作 小号 也是类型 double
?
谢谢
因为这个特殊的超载知道你正在开始 int
值,它知道你没有使用十进制值。将每个值转换为a double
然后添加 double
值一起可能效率较低,如果你有足够大的值集合,肯定会让你面临浮点不精确问题的可能性。
更新
我只是做了一个快速的基准测试,它需要 大约50%的时间 超过两倍 平均 double
和平均值一样 int
秒。
首先,我注意到,除非你超过一个长的边界,否则不会出现异常。你打算怎么做?每个int最多约为20亿,而long的顶部约为8亿亿,因此这意味着您必须至少采用超过40亿的平均值才能触发异常。这是你经常需要解决的那种问题吗?
假设是为了争论。在双精度数中进行数学运算会失去精度,因为双精度算术四舍五入到大约十五个小数位。看:
using System;
using System.Collections.Generic;
static class Extensions
{
public static double DoubleAverage(this IEnumerable<int> sequence)
{
double sum = 0.0;
long count = 0;
foreach(int item in sequence)
{
++count;
sum += item;
}
return sum / count;
}
public static IEnumerable<T> Concat<T>(this IEnumerable<T> seq1, IEnumerable<T> seq2)
{
foreach(T item in seq1) yield return item;
foreach(T item in seq2) yield return item;
}
}
class P
{
public static IEnumerable<int> Repeat(int x, long count)
{
for (long i = 0; i < count; ++i) yield return x;
}
public static void Main()
{
System.Console.WriteLine(Repeat(1000000000, 10000000).Concat(Repeat(1, 90000000)).DoubleAverage());
System.Console.WriteLine(Repeat(1, 90000000).Concat(Repeat(1000000000, 10000000)).DoubleAverage());
}
}
在这里,我们用双算术平均两个系列:一个是{十亿,十亿,十亿......一千万......十亿,一,一......九千万次}和一个是相同的顺序与第一个和数十亿最后。如果运行代码,则会得到不同的结果。差别不大,但不同,序列越长,差异就越大。长算术是准确的;双重算术可能会结束 一切 计算,这意味着 大规模的 错误会随着时间的推移而累积。
单独执行操作会导致浮点舍入误差累积,这似乎是非常意外的。这是在对浮点数进行操作时所期望的那种事情,但在使用整数时进行操作时却没有。