首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ARR[0]/N+ARR[1]/N...+ARR[N-1]/N或(ARR[0]+ARR[1]...+ARR[N-1])/N是更准确的方法吗?

ARR[0]/N+ARR[1]/N...+ARR[N-1]/N或(ARR[0]+ARR[1]...+ARR[N-1])/N是更准确的方法吗?
EN

Stack Overflow用户
提问于 2014-09-28 18:23:47
回答 3查看 208关注 0票数 1

有什么更精确的方法来计算数字集的平均值,ARR[0]/N+ARR[1]/N...+ARR[N-1]/N还是(ARR[0]+ARR[1]...+ARR[N-1])/N?(ARR是数字的集合,N是该集合中数字的计数)

考虑一下,我有一组从0.01.0的数字集(它们是双浮点数),其中有数千个,甚至数百万。

我乐于使用新的方法,比如递归平均(将平均双单元格转换为数组,然后再对其进行平均处理,直到它输出一个单元格数组)。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-09-28 18:33:25

如果接近于零的值非常接近于零,则在求和中会出现舍入(可能是舍入误差向上或向下)的问题,或者如果对大量数字进行求和,则会遇到任何数字范围的问题。解决这个问题的一种方法是使用一个求和函数,它只添加具有相同指数的数字(直到调用getsum()来得到总和,其中它尽可能地保持指数接近)。示例C++类来完成此操作(注释代码是使用Visual编译的,在uint64_t可用之前编写)。

代码语言:javascript
复制
//  SUM contains an array of 2048 IEEE 754 doubles, indexed by exponent,
//  used to minimize rounding / truncation issues when doing
//  a large number of summations

class SUM{
    double asum[2048];
public:
    SUM(){for(int i = 0; i < 2048; i++)asum[i] = 0.;}
    void clear(){for(int i = 0; i < 2048; i++)asum[i] = 0.;}
//  getsum returns the current sum of the array
    double getsum(){double d = 0.; for(int i = 0; i < 2048; i++)d += asum[i];
                    return(d);}
    void addnum(double);
};

void SUM::addnum(double d)      // add a number into the array
{
size_t i;

    while(1){
//      i = exponent of d
        i = ((size_t)((*(unsigned long long *)&d)>>52))&0x7ff;
        if(i == 0x7ff){         // max exponent, could be overflow
            asum[i] += d;
            return;
        }
        if(asum[i] == 0.){      // if empty slot store d
            asum[i] = d;
            return;
        }
        d += asum[i];           // else add slot to d, clear slot
        asum[i] = 0.;           // and continue until empty slot
    }
}

使用sum类的示例程序:

代码语言:javascript
复制
#include <iostream>
#include <iomanip>
using namespace std;

static SUM sum;

int main()
{
double dsum = 0.;
double d = 1./5.;
unsigned long i;

    for(i = 0; i < 0xffffffffUL; i++){
        sum.addnum(d);
        dsum += d;
    }
    cout << "dsum             = " << setprecision(16) << dsum << endl;
    cout << "sum.getsum()     = " << setprecision(16) << sum.getsum() << endl;
    cout << "0xffffffff * 1/5 = " << setprecision(16) << d * (double)0xffffffffUL << endl;

    return(0);
}
票数 2
EN

Stack Overflow用户

发布于 2014-09-28 18:26:03

(ARR[0]+ARR[1]...+ARR[N-1])/N更快、更准确,因为您省略了使用N的无用的分区,这些分区既减慢了处理速度,又增加了计算中的错误。

票数 0
EN

Stack Overflow用户

发布于 2014-09-28 18:48:01

如果你有一堆浮点数,得到平均值的最准确的方法是这样:

代码语言:javascript
复制
template<class T> T mean(T* arr, size_t N) {
    std::sort(+arr, arr+N, [](T a, T b){return std::abs(a) < std::abs(b);});
    T r = 0;
    for(size_t n = 0; n < N; n++)
        r += arr[n];
    return r / N;
}

要点:

  • 首先添加最小幅度的数字以保留有效数字。
  • 只有一个除法,以减少舍入误差。

不过,中间金额可能会变得太大。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26088099

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档