如何求一组大数的平均值?我有一堆数字,可能在千兆字节范围内。第一个问题是我无法将所有这些都存储在内存中。其次,任何添加这些的尝试都会导致溢出。我想使用更多滚动平均值,但它需要准确。有任何想法吗?这些是浮点数。这不是从数据库中读取的,而是从多个来源收集的CSV文件。它必须准确,因为它存储为秒的一小部分(例如;0.293482888929),滚动平均值可以是0.2和0.3之间的差异。它是一组#,指示用户何时响应某些表单操作。例如,显示消息框时按“确定”或“取消”需要多长时间。发送给我的数据以秒为单位存储。偏秒;例如1.2347秒。将它转换为毫秒,我会溢出int、long等……非常快。即使我不转换它,我仍然很快溢出它。我认为下面的答案之一是正确的,也许我不必100%准确,只需查看特定StdDev内的某个范围内,我就足够接近了。您可以从您的集合(“人口”)中随机抽样以获得平均值(“平均值”)。准确性将取决于样本的可变性(由“标准差”或方差决定)。优点是您有数十亿个观察结果,您只需要对其中的一小部分进行抽样即可获得可比较的准确性或您选择的“置信区间”。如果条件合适,这将减少您必须做的工作量。这是一个包含随机序列生成器的C#数字库。只需创建一个随机数字序列,引用元素数组中的索引(从1到x,数组中的元素数)。取消引用以获取值,然后计算您的均值和标准差。如果您想测试数据的分布,请考虑使用卡方拟合检验或KS检验,您可以在许多电子表格和统计软件包(例如R)中找到它们。这将有助于确认此方法是否可用。整数还是浮点数?如果它们是整数,您需要通过读取数字并记录您看到的每个值的数量来累积频率分布。这很容易平均。对于浮点数,这是一个问题。给定浮点数的总体范围和实际分布,您必须计算出一个bin大小,以在不保留所有数字的情况下保留您想要的精度。编辑首先,您需要对数据进行采样以获得均值和标准差。几千点应该足够了。然后你需要确定一个可观的范围。人们选择平均值附近的±6σ(标准差)。您可以根据需要将此范围划分为多个桶。实际上,桶的数量决定了平均值中有效数字的数量。所以选择10,000或100,000个桶以获得4或5位数的精度。由于这是一个测量值,因此您的测量值很可能只有两位或三位数字。编辑您会发现初始样本的均值非常接近任何其他样本的均值。任何样本均值都接近总体均值。您会注意到大多数(但不是全部)平均值都在1个标准差之内。你应该发现测量误差和误差都大于标准偏差。这意味着样本均值与总体均值一样有用。滚动平均值不会像其他任何东西一样准确吗(我的意思是折扣舍入误差)?由于所有拆分,它可能会有点慢。您可以将一批数字分组并递归地对它们进行平均。就像将100个数字平均100次,然后对结果进行平均。那将减少颠簸和大多数添加。实际上,如果你一次加上256或512,你可以将结果移动8或9位(我相信你可以通过简单地改变浮点尾数来做到这一点)-这将使你的程序非常快,可以写成仅用几行代码递归(不包括移动尾数的不安全操作)。也许除以256已经使用了这个优化?我可能不得不加快测试速度并除以255和256,看看是否有一些大的改进。我猜不会。你的意思是32位和64位数字。但为什么不使用合适的RationalBigNum库呢?如果您有这么多数据并且想要一个精确的平均值,那么只需对其进行编码。}publicBignumDenominator{get;放;}}classBigMeanr{publicstaticintMain(string[]argv){varsum=newRationalBignum(0);varn=newBignum(0);使用(vars=newFileStream(argv[0])){使用(varr=newBinaryReader(s)){try{while(true){varflt=r.读取单个();rat=newRationalBignum(flt);总和+=老鼠;n++;}}catch(EndOfStreamException){中断;}}}Console.WriteLine("均值是:{0}",sum/n);记住,except的数值类型比编译器给你的要多得多。您可以将数据分成几组,例如1000个数字,均值,然后均值。这是一个经典的分而治之问题。问题是一组大数的均值与前半部分的均值和后半部分的均值相同。换句话说:AVG(A[1..N])==AVG(AVG(A[1..N/2]),AVG(A[N/2..N]))这是一个简单的C#递归解决方案。它通过了我的测试,应该完全没问题。publicstructSubAverage{publicfloatAverage;公共整数计数;};staticSubAverageAverageMegaList(ListaList){if(aList.Count诀窍是你担心溢出。在这种情况下,这一切都归结为执行顺序。基本公式是这样的:给定:A=当前平均值C=项目数V=序列中的下一个值下一个平均值(A1)是:(C*A)+V。A1=-----------C+1危险在于您担心在序列的过程中,应该保持相对可控的A,C会变得非常大。最终C*A将溢出整数或双精度类型。我们可以尝试的一件事是像这样重写它以减少溢出的可能性:A1=C/(C+1)*A/(C+1)+V/(C+1)这样,我们永远不会乘以C*A并且只适用于较小的数字。但现在重点是分工结果。如果C非常大,C/C+1(例如)在约束为普通浮点表示时可能没有意义。我能建议的最好的是在这里使用C的最大类型。这是在伪代码中执行此操作的一种方法:average=firstcount=1more:count+=1diff=nextaverage+=diff/countreturn很抱歉评论晚了,但是没有JoelCoehoorn提供的上述公式是否被错误地重写了?我的意思是,基本公式是正确的:给定:A=当前平均值C=项目数V=序列中的下一个值下一个平均值(A1)是:A1=((C*A)+V)/(C+1)而不是:A1=C/(C+1)*A/(C+1)+V/(C+1)我们不应该:A1=C/(C+1)*A+V/(C+1)这可以解释kastermester的帖子:“我的数学在这里徘徊-你有C,你说“去无穷大”或者至少是一个非常大的数字,然后:C/(C+1)到1。A/(C+1)变为0。V/(C+1)变为0。所以总而言之:A1??=1*0+0如此快速地将A1推向0-似乎有点偏离。-kastermester"因为我们会有A1=1*A+0,即A1到A,这是正确的。我已经用这种方式计算平均值很长时间了,上述精度问题对我来说从来都不是问题。根据数字的范围,最好有一个数组,下标是你的数字,值是这个数字的数量,你可以从这里开始计算如果数字是int,累计总数很长。如果号码很长...您使用的是什么语言?在Java中,您可以在BigInteger中累加总计,这是一个增长到所需大小的整数。您始终可以编写自己的类来重现此功能。它的要点只是制作一个整数数组来保存每个“大数”。两个数相加时,从小数开始循环。如果加法的结果设置了高位,则清除该位并将该位移动到下一列。另一种选择是一次求出1000个数字的平均值。保留这些中间结果,然后在完成后对它们进行平均。为什么浮点数的和会溢出?为了让它工作,你需要有一些接近最大浮点值的东西,这听起来很奇怪。如果你正在处理整数,我建议使用BigInteger,或者将集合拆分为子集,递归地对子集进行平均,然后对平均值进行平均。如果你正在处理浮动,它会变得有点奇怪。滚动平均数可能会变得非常不准确。我建议使用滚动平均值,它只会在遇到溢出异常或收集结束时更新。因此,有效地将集合划分为非溢出集合。我的两个想法:为什么不在计算平均值之前缩小数字(缩小)?以上是C#学习教程:如何求一组大数的平均值?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
