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