如何获得与c ++中的平均值最接近的数字?

时间:2013-10-26 14:55:04

标签: c++ pointers memory

我想要实现的是获取存储在数组中的数字的平均值,并找到最接近它的数字。 我的代码编译,但刚刚启动后出错。我认为这与内存处理有关(我对指针等没有信心) 一些好人可以看看我的代码并告诉我它有什么问题吗? (不要对我很难,我是初学者)

#include <iostream>
#include <cmath>

using namespace std;

double* aver(double* arr, size_t size, double& average);

int main()
{
    double arr[] = {1,2,3,4,5,7};
    size_t size = sizeof(arr)/sizeof(arr[0]);
    double average = 0;
    double* p = aver(arr,size,average);
    cout << *p << " " << average << endl;
}

double* aver(double* arr, size_t size, double& average){
    int i,j,sum;
    double* m = 0;
    int tmp[7];
    for(i=0;i<size;i++)
        sum += arr[i];
    average = sum/size;
    for(j=0;j<size;j++){
        tmp[j] = arr[j] - average;
        if(abs(tmp[j])>*m)
        *m = tmp[j];
    }
    return m;
}

3 个答案:

答案 0 :(得分:3)

以下

double* m = 0;

m设置为空指针。任何取消引用它的尝试都会导致未定义的行为。

将上述内容更改为:

double m = 0;

并将*m替换为m,并将函数的返回类型更改为double

最后,您不需要tmp数组。

答案 1 :(得分:2)

1 您的代码出了什么问题?指针的使用以及由此产生的初学者错误。

2 如何计算C ++中的平均值?大致相同:

#include <iostream>
#include <iomanip>
#include <vector>
#include <numeric>

int main()
{
  std::vector<double> arr = {1,2,3,4,5,7};
  auto average = std::accumulate(std::begin(arr),std::end(arr),0.0) / arr.size();
  std::cout  << " average = " << std::setprecision(16) << average << std::endl;
}

(注意:使用选项-std=c++11编译)

3 如何找到最接近它的数字(平均值)?如果您的计算机符合IEEE标准(大多数情况下,但某些编译器优化违反了该规则),则任何算术的结果都会舍入到最接近可表示的数字。所以,这里没有什么特别需要做的。但是,数字的累积会受到舍入误差的影响,从而导致精度损失。这可以通过以其绝对值的降序累加数字来最小化,尽管存在计算累积仍然相当不精确的病理情况。详细了解维基百科。

4 如何找到最接近它的数组值(平均值)? Johan的答案中显示了一种方法。但是,它通过执行部分排序不必要地改变了阵列。更好地使用std::min_element (无需std::transform):

auto comp = [average](double left, double right)
  { return std::abs(left-average) < std::abs(right-average); };
auto closest = std::min_element(std::begin(arr), std::end(arr), comp);
std::cout << " value closest to average was "
          << *closest << " at position "
          << (closest-std::begin(arr))
          << std::endl;

答案 2 :(得分:1)

根据沃尔特的回答,添加“最接近平均值的发现值”部分:

#include <iostream>
#include <vector>
#include <numeric>
#include <cmath>
#include <algorithm>

int main()
{
  std::vector<double> arr = {1,2,3,4,5,7};
  auto average = std::accumulate(std::begin(arr),std::end(arr),0.0) / arr.size();
  std::cout  << " average = " << average << std::endl;
  auto comp = [average](double left,double right){
     return std::abs(left-average)<std::abs(right-average);  };
  auto mini=std::min_element(std::begin(arr),std::end(arr),comp);
  std::cout << "value closest to average was " << *mini <<std::endl;
}

使用转换的替代(较慢)实现(减少对fab的调用次数,但是复制):

#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>

int main()
{
  std::vector<double> arr = {1,2,3,4,5,7};
  auto average = std::accumulate(std::begin(arr),std::end(arr),0.0) / arr.size();
  std::cout  << " average = " << average << std::endl;
  auto pred=[average](double x){return std::abs(x-average);};
  auto arrcpy = arr;
  std::transform(std::begin(arr),std::end(arr),std::begin(arrcpy),pred);
  auto result = std::min_element(std::begin(arrcpy),std::end(arrcpy));
  std::cout << "value closest to average was: " << arr[result-std::begin(arrcpy)];
}

使用标准算法通常是正确的,因为它更易于维护。在这种情况下,我没有找到像这样快速使用标准算法的方法(比上面使用10e7元素和-O2的第一个解决方案快30%):

  std::pair<double,double> smallest(std::abs(average-arr[0]),arr[0]);
  for(auto a: arr){
    auto v=std::abs(average-a);
    if(v<smallest.first){
       smallest={v,a};
    }
  }
  std::cout << "value closest to average was " << smallest.second <<std::endl;