1

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

#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;
}
4

3 回答 3

3

以下

double* m = 0;

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

将以上内容更改为:

double m = 0;

并替换*mm到处,还将函数的返回类型更改为 just double

最后,您不需要tmp数组。

于 2013-10-26T14:56:40.767 回答
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如何找到最接近它的数组值(平均值)?约翰的回答中显示了一种方法。但是,它通过执行部分排序不必要地改变了数组。更好的使用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;
于 2013-10-26T15:04:25.050 回答
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;
}

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

#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;
于 2013-10-26T15:23:18.163 回答