std::accumulate is supposed to be able to take either three or four arguments. In the former case it's just when you want to add the numbers in a container; in the latter case it's when you want to first apply a function and then add them. I've written code that generates a vector of random doubles and then does some stuff to them: first it performs an x->x^2 transform using std::transform, then adds them up with std::accumulate, and lastly combines the two actions into one using the four-argument version of std::accumulate.
Everything works except for step 3. Looking at the example code to be found at http://www.cplusplus.com/reference/numeric/accumulate/, I can't see any reason why this shouldn't work, but I'm getting a "Too many arguments error" when compiling (I'm using XCode. For some reason it doesn't tell me the line number, but I've narrowed it down to the second usage of std::accumulate). Any insights?
#include <numeric>
#include <time.h>
#include <math.h>
using std::vector;
using std::cout;
using std::endl;
double square(double a) {
return a*a;
}
void problem_2_1() {
vector<double> original;
//GENERATE RANDOM VALUES
srand((int)time(NULL));//seed the rand function to time
for (int i=0; i<10; ++i) {
double rand_val = (rand() % 100)/10.0;
original.push_back(rand_val);
cout << rand_val << endl;
}
//USING TRANSFORM
vector<double> squared;
squared.resize(original.size());
std::transform(original.begin(), original.end(), squared.begin(), square);
for (int i=0; i<original.size(); ++i) {
std::cout << original[i] << '\t' << squared[i] << std::endl;
}
//USING ACCUMULATE
double squaredLength = std::accumulate(squared.begin(), squared.end(), 0.0);
double length = sqrt(squaredLength);
cout << "Magnitude of the vector is: " << length << endl;
//USING 4-VARIABLE ACCUMULATE
double alt_squaredLength = std::accumulate(original.begin(), original.end(), 0.0, square);
double alt_length = sqrt(alt_squaredLength);
cout << "Magnitude of the vector is: " << alt_length << endl;
}
The fourth argument to that std::accumulate overload needs to be a binary operator. Currently you are using a unary one.
std::accumulate performs a binary operation between successive elements in a container, hence the need for a binary operator. The fourth argument replaces the default binary operation, addition. It does not apply a unary operation and then perform addition. If you want to square the elements and then add them, you would need something like
double addSquare(double a, double b)
{
return a + b*b;
}
Then
double x = std::accumulate(original.begin(), original.end(), 0.0, addSquare);
Related
I was trying to sort the areas of a circle in an ascending order. First, the user chooses the number of circles, then he should type the coordinates and the area of his circles. In the end the program should output the radius of a circle in an ascending order.But the output of areas is not in an ascending order(It's the same as input). What is my problem?
#include<iostream>
#include <algorithm>
using namespace std;
struct circle {
int 반지름;
int coordinates;
int coordinates2;
};
bool compare(circle a, circle b){
if(a.반지름 < b.반지름)
return 1;
else
return 0;
}
int main()
{
int n = 1;
int* ptr1;
ptr1 = new int;
circle* circle1;
circle1 = new (nothrow) circle[5];
circle1[0].반지름;
circle1[0].coordinates;
circle1[0].coordinates2;
circle1[1].반지름;
circle1[1].coordinates;
circle1[1].coordinates2;
circle1[2].반지름;
circle1[2].coordinates;
circle1[2].coordinates2;
circle1[3].반지름;
circle1[3].coordinates;
circle1[3].coordinates2;
circle1[4].반지름;
circle1[4].coordinates;
circle1[4].coordinates2;
circle1[5].반지름;
circle1[5].coordinates;
circle1[5].coordinates2;
cout << "Enter the number of circles: ";
cin >> *ptr1;
cout << "중심 좌표, 반지름 : " << endl;
for (int i = 0; i < *ptr1; i++) {
cin >> circle1[i].coordinates >> circle1[i].coordinates2 >> circle1[i].반지름;
}
sort(circle1, circle1 + 1, compare);
for (int i = 0; i < *ptr1; i++) {
cout << "The result: " << circle1[i].coordinates << " " << circle1[i].coordinates2 << " " << circle1[i].반지름 << endl;
}
delete[] circle1;
delete ptr1;
return 0;
}
That's not C++, that's a strange and hybrid thing between C and C++... And this is your main problem. You're mixing up things that should not be mixed, not if you don't know PERFECLY what you do - and obviously, it's not the case, otherwise your code should have worked, and it haven't.
Corrected code, in real C++:
#include <iostream> // std::cout & co
#include <algorithm> // std::sort
#include <cstdlib> // std::rand & co
#include <vector> // std::vector
struct circle {
int area ;
int x ;
int y ;
} ;
// For printing a circle easily and not repeat code X times.
// Print as: [area#(x,y)]
std::ostream& operator<<(std::ostream& os, const circle& c) {
os << "[" << c.area << "#(" << c.x << "," << c.y << ")]" ;
return os;
}
int main() {
// Set a constant seed: each run will produce the same result, if needed to debug.
std::srand(1234) ;
// 5 circles declared within a vector, not a C array.
auto circles = std::vector<circle>(5) ;
// Fill the vector.
std::cout << "Original circles:" << std::endl ;
// Use a simpler for syntax.
for ( auto& c: circles ) {
// Random values used. The fixed seed will always give the same values on each run.
c.area = 10 + std::rand() % 50 ;
c.x = std::rand() % 1920 ;
c.y = std::rand() % 1080 ;
// Print the circle.
std::cout << "\t" << c << std::endl ;
}
// Sort the vector, use a lambda expression for the compare operator.
// No need for a "real" function, if it's used only once and only there.
// Compare function returns directly a bool, not an integer.
std::sort(circles.begin(), circles.end(), [](const circle& a, const circle& b) -> bool { return (a.area<b.area) ; });
// Display sorted vector.
std::cout << std::endl << "Sorted circles:" << std::endl ;
for ( const auto& c: circles )
std::cout << "\t" << c << std::endl ;
return 0;
}
Still strange that you use area instead of radius or diameter, but anyway... Area is for a disc, not a circle, but that's mathematical precision at this stage.
First, if you print a structure like circle at least twice, do a stream operator to do it only once. Please note that I send directly the structure to std::cout, after...
Then, I use a C++ container, not a C allocated array. You can still allocate memory for big amount of data, but for this example, that's unneeded.
Then, instead of asking for each values, I use std::rand() to fill them. Easier. Can be used in any language. Refined trick: I initialize the pseudo-random generator to a constant, fixed value, so each time the program is run, it will generate the exact same sequence of pseudo-random numbers - this can vary on each machine / OS / compiler / compiler version but it will be constant on YOUR machine during your tests, and it can be debugged easily.
Please also note that I use a compact form of for that will iterate on the whole circles container, giving me each time a circle& (reference) on each element so that I can modify it - needed for initialization.
Now, the sort itself: from begin() to end() of the container, using a lambda expression to define the compare operator. Please note that I return directly the result of the comparison, which is a bool, and that I don't cast an int to a bool implicitely...
Finally, print the result. Note that this time, I ask for a const auto& reference, to be sure to not modify data by mistake.
Nothing to delete, C++ will take care of that.
An example output, on my machine:
Original circles:
[28#(213,881)]
[18#(16,157)]
[34#(1468,816)]
[14#(745,718)]
[31#(143,818)]
Sorted circles:
[14#(745,718)]
[18#(16,157)]
[28#(213,881)]
[31#(143,818)]
[34#(1468,816)]
I want to display the range of x and f(x) and keep f(x) in array but i always get this error:
invalid type 'float*[float]' for array subscript
can someone help me? I'm still stuck.
Here's the code:
#include <iostream>
#include <cmath>
#include <math.h>
using std::cin;
using std::cout;
using namespace std;
void displayValue(float funx[], float j, float x);
int main()
{
float num9[]={};
float a, r;
displayValue(num9, a, r);
return 0;
}
void displayValue(float funx[], float j, float x)
{
float i;
cout << "Please enter range of x: " << endl;
for (i=0; i<1; i++)
{
cin >> x >> j;
}
for (float i=1; i<=160.5; i++)
{
x+=0.5;
funx[i]=1/sin(x)+1/tan(x);
//1.2 Display f(x) and x within the range
}cout << x << " = " << funx[i] << "\n";
}
The problems you're trying to solve aren't actually problems you need to solve. There's a lot going wrong in this code that can simply be removed because you're using the wrong tools.
You don't need an array here. If you did you'd need to allocate one, not pass in something that's empty, or you'd be using it out of bounds. In C++ for arrays like this use std::vector.
That being said, here's a simplified version of the code:
#include <iostream>
#include <cmath>
#include <math.h>
// Don't add "using namespace std", that separation exists for a reason.
// Separate the math function to make it clear what's being done
float f(const float x) {
return 1/sin(x)+1/tan(x);
}
// Define your functions before they're used to avoid having to declare
// then later define them.
void displayValue(const float min, const float max, const float step = 0.5)
{
for (float x = min; x <= max; x += step)
{
// Note how the f(x) function here is a lot easier to follow
std::cout << "f(" << x << ") = " << f(x) << std::endl;
}
}
int main()
{
std::cout << "Please enter range of x: " << std::endl;
// Capture the range values once and once only
float min, max;
std::cin >> min >> max;
// Display over the range of values
displayValue(min, max);
return 0;
}
There's some important C++ fundamentals here:
float num9[]={}; is not an empty array that you can later add to, it is a permanently zero-length array, or in other words, it's useless.
Pay close attention to the variables you've defined and avoid defining them twice in the same scope.
Turn on all your compiler warnings while you're learning to be alerted to potential problems. C++ is full of nuances and gotchas.
This is the assignment:
Write two functions that calculate the mean and standard deviation.
Your functions shall implement the following prototypes:
double mean(vector<double>x);
double sd(vector<double>x);
b. Place these functions in a file named “statfun.cpp”.
c. Place their function definitions in a file named “statfun.h”.
Write a main() function in a file named “lab1.cpp”.
Prompt the user to input 10 floating-point values and store them in a vector v.
Print vector v on a single line with each element separated by a space.
Call your functions mean(v) and sd(v) ...
I know how to code the formula for mean, but I'm not sure how to code the formula for standard deviation using vectors. I'm even less sure of how to do this with different files involved. I'm fully aware my code is garbage, but there are so many things I'm not sure of, I don't know what to tackle first.
Edit: Updated the code
//statfun.h
#include <iostream>
#include <vector>
#ifndef STATFUN_H
#define STATFUN_H
using namespace std;
double mean(vector<double> v);
double sd(vector<double> v);
#endif
//statfun.cpp
#include <iostream>
#include <cmath>
#include <vector>
#include "statfun.h"
#ifndef STATFUN_CPP
#define STATFUN_CPP
using namespace std;
double mean(const vector<double> v) {
double result;
double sumVal = 0.0; //Calculating sum of all values
for (int i = 0; i < v.size(); ++i) {
sumVal = sumVal + v.at(i);
}
result = sumVal / v.size(); //Calculating mean
return result;
}
double sd(const vector<double> v) {
double total = 0;
for (int i = 0; i < 10; ++i) { //Calcuating standard deviation
double mean_value = mean(v);
int length = v.size()
total = total + (val - mean_value)*(val - mean_value);
}
return sqrt(total / length);
}
#endif
//lab1.cpp
#include "statfun.cpp"
#include <iomanip>
using namespace std;
vector<double> v;
int main() {
cout << "Enter 10 numbers: " << endl;
float userInput = 0;
for (int i = 0; i < 10; ++i) {
cin >> userInput;
v.push_back(userInput);
}
for (int i = 0; i < 10; ++i) {
cout << v.at(i) << " ";
}
cout << endl;
cout.precision(3);
cout << mean(v) << " " << sd(v) << endl;
cout.precision(5);
cout << scientific << mean(v) << " " << sd(v) << endl;
return 0;
}
You made many mistakes and your code has much to improve.
Let me show you me by me.
The header
Since one file can include header multiple times, to prevent any side effect of this, an include guard is required for each header file.
// statfun.h
#ifndef __statfun_H__
# define __statfun_H__
# include <vector>
double mean(const std::vector<double>&);
double sd(const std::vector<double>&);
#endif
BTW, a function declaration can abbreviate the arguments' name.
Reference
The second mistake you made is that you didn't use reference. In c++, an object is by default passed by value.
Note: This is just like R, except it doesn't have language level copy-on-write semantics, but user-defined class can implement this, classes defined in std namespace can also implement this.
So in order to prevent costy copy, reference is made.
double mean(const std::vector<double>&);
Here I used const left-value reference (const &), since mean will not modify the vector passed in.
Function blocks.
In c++, a function is defined as below:
return_value func_name(type1 arg1 /* , type2 arg2, ... */)
{
// The function body goes here:
}
So
// statfun.cpp
// c++11
#include "statfun.h"
#include <cmath>
double mean(const std::vector<double> &v)
{
double sum = 0;
for (auto &each: v)
sum += each;
return sum / v.size();
}
double sd(const std::vector<double> &v)
{
double square_sum_of_difference = 0;
double mean_var = mean(v);
auto len = v.size();
double tmp;
for (auto &each: v) {
tmp = each - mean_var;
square_sum_of_difference += tmp * tmp;
}
return std::sqrt(square_sum_of_difference / (len - 1));
}
Compile-time variable type deduction
As you might have noticed in the code above, I used auto len = v.size(), which is a c++11 language feature -- auto.
Since c++11, c++ can deduce the return type of function calls at compile-time. So instead of define variable like typename std::vector<double>::size_type len = v.size(), we now have auto len = v.size().
range-for loop
If you have learnt python, then you must know range-for. Since c++11, c++ can also do this:
for (auto &each: v) {
// Loop body
}
where v can be std::vector or any other container in c++.
IO error check
Last but not least, you didn't check if any of these IO you performed on std::cout or std::cin succeeds or not!
Using std::cout or std::cin, you have to check stream state by std::cout.fail() every time after you performed an IO, or use the following code:
std::cout.exceptions(std::ios_base::failbit | std::ios_base::badbit);
std::cin.exceptions(std::ios_base::failbit | std::ios_base::badbit);
To make std::cout and std::cin throws when an IO fails.
I personally like to not handle this error and let the exception terminates the program, since there is nothing you can do to cleanup and resume the control flow of the program.
Below is the last piece of code:
// lab1.cpp
// c++11
#include "statfun.h"
#include <iostream>
auto get_use_input() -> std::vector<double>
{
std::vector<double> v;
v.reserve(10);
double userInput;
for (int i = 0; i != 10; ++i) {
std::cout << "Please enter the " << i + 1 << " number: ";
std::cin >> userInput;
std::cout << std::endl;
v.push_back(userInput);
}
return v;
}
void print_vec(const std::vector<double> &v)
{
std::cout << "Vector: ";
for (auto &each: v)
std::cout << each << " ";
std::cout << std::endl;
}
int main() {
// Configure std::cout and std::cin to throw if io fails.
std::cout.exceptions(std::ios_base::failbit | std::ios_base::badbit);
std::cin.exceptions(std::ios_base::failbit | std::ios_base::badbit);
/*
* With "-O3" or [c++17, copy elision](https://en.cppreference.com/w/cpp/language/copy_elision),
* the cost of initializing an object using the return value of anther function is nearly zero.
*/
std::vector<double> v = get_use_input();
print_vec(v);
std::cout.precision(3);
std::cout << "mean: " << mean(v) << " sd: " << sd(v) << std::endl;
std::cout.precision(5);
std::cout <<std::scientific << "mean: " << mean(v) << " sd: " << sd(v) << std::endl;
return 0;
}
To build this program, you must have a c++ compiler that supports c++11 and pass -std=c++11 to the compiler.
PS: You can also use -std=c++14 or -std=c++17.
A simple Makefile to build the program:
cxx = ${CXX}
# The flags
CPPFLAGS := -std=c++11
# The two line below is the flags I used for clang++-8
# CPPFLAGS := -std=c++17 -Ofast -pipe -flto
# LDFLAGS := -flto -pipe -Wl,--icf=all,-O2,--as-needed,--strip-all,--plugin-opt=O3
lab1: lab1.o statfun.o
$(CXX) $(LDFLAGS) $^ -o $#
statfun.o: statfun.h
lab1.o: statfun.h
.PHONY: clean
rm -f lab1.o statfun.o lab
I believe your first issue is in understanding the file structure of your stats assignment. Tackle this first. Understanding headers. More on headers and function calls from other files.
The .cpp files will contain implementation of logic, the .h files are headers that should declare definitions of objects and functions. When you include files at the top of your code, generally think of this as having all the code from that file above the current file.
Example:
statfun.h
double mean(vector<double> v);
// other **declaration** stuff....
lab1.cpp at the top of the file
#include "statfun.h" // equivalent to copy/pasting 'double mean(vector<double> v); and other declarations' into your lab1.cpp
// This is to help with cleanliness of your file structure.
// You'll thank yourself when projects become bigger.
Note: lab1.cpp includes statfun.cpp which includes statfun.h; implicitly, lab1.cpp includes statfun.h which means you don't have to include statfun.h in lab1, although typically the header is included, not the cpp file. You must avoid circular dependencies which you do with the ifndef.
b. statfun.cpp should be the place where you code all of your logic for the mean and standard deviation.
example:
statfun.cpp
double mean(vector<double> v) {
// Your mean calculation logic here.
return mean;
}
double sd(vector<double> x) {
// Your standard deviation calculation logic here.
return sd;
}
c.
So you have lab1.cpp which will be compiled to produce some runnable binary. As the entry point of your program, it should include an int main() function. This main function needs to ask for user input (search the webs for how to take std input).
Store the standard input as a vector (this is still in your main function).
Use cout to print to standard out. 'cout << name_of_variable_with_vector_input_from_user;' (still in your int main())
Call/use the functions you wrote in statfun.cpp (notably mean() and sd()). Maybe store their return values in a variable to use later. Since you need to call the statfun functions here, the lab1.cpp entry file must include statfun.h so that it knows what code to execute when you call those functions.
Now that this file structure logic is complete. A simple way to calculate std deviation in pseudocode:
statfun.madeuplanguage
type sd(vector<type> values) {
type total = 0;
type mean_value = mean(values);
for val in values {
total += (val - mean_value)^2;
}
total /= values.length;
return sqrt(total);
}
This in mind, I would structure the lab1.cpp as follows.
lab1.cpp
int main() {
vector<double> v;
// take input and store in v.
// std out - v
double mean_val = mean(v);
double std_dev = sd(v);
// std out - mean_val and std_dev
}
If you have any questions about implementing the above pseudocode in C++, great! It's your assignment/class, so take care to search the webs in doing extremely specific things in C++ (e.g. iterating on a vector, squaring, square rooting, etc...). Good luck learning.
I'm trying to use cxx-11's std::unique() to find
the unique elements in an array:
#include <iostream>
#include <algorithm>
#include <vector>
#include <typeinfo>
int main(){
const int n=11;
double x[n],a3[n],a1[n];
x[0]=-0.717778;
x[1]=-0.496843;
x[2]=-0.429063;
x[3]=-0.3596;
x[4]=-0.205607;
x[5]=0.0730536;
x[6]=0.138018;
x[7]=0.585526;
x[8]=2.40104;
x[9]=3.75268;
x[10]=4.55704;
a3[0]=0.790832;
a3[1]=0.569896;
a3[2]=0.502116;
a3[3]=0.432653;
a3[4]=0.343625;
a3[5]=0.512472;
a3[6]=0.56708;
a3[7]=1.01459;
a3[8]=2.32799;
a3[9]=3.67962;
a3[10]=4.48398;
std::cout.precision(10);
std::copy(a3,a3+n,a1);
for(int i=0;i<n;i++) a1[i]+=x[i];
std::sort(a1,a1+n);
for(int i=0;i<n;i++) std::cout << a1[i] << std::endl;
std::cout << "---" << std::endl;
int n_1=std::unique(a1,a1+n)-a1;
std::cout << "length of unique subvector " << n_1 << std::endl;
std::cout << "---" << std::endl;
for(int i=0;i<n_1;i++) std::cout << a1[i] << std::endl;
std::cout << "---" << std::endl;
}
but when I'm running this code (link to coliru)
it returns:
original array
0.073053
0.073053
0.073053
0.073054
0.138018
0.5855256
0.705098
1.600116
4.72903
7.4323
9.04102
---
length of unique subarray 10
---
unique array
0.073053
0.073053
0.073054
0.138018
0.5855256
0.705098
1.600116
4.72903
7.4323
9.04102
---
the unique array still contains a duplicate (and so is wrong)!
what am I doing wrong?
Let's try with a bit more precision, std::cout.precision(20):
0.073052999999999979064
0.073053000000000034575
0.073053999999999952308
0.13801800000000000179
0.58552559999999997942
0.70509800000000000253
1.6001160000000000938
4.7290299999999998448
7.4322999999999996845
9.0410199999999996123
Since most decimal fractions can't be represented exactly by a binary floating point format, slightly different rounding errors cause slightly different results.
In general, you can't expect the results of different floating point calculations to be exactly equal, even if the corresponding calculations applied to mathematical real numbers would be.
You could instead test for "almost equality", carefully choosing a tolerance that's appropriate for your numerical domain. unique allows you to specify your own predicate, instead of a simple equality test:
std::unique(a1,a1+n,[](double x, double y){return std::abs(x-y) < tolerance;});
How about:
int n_1 = std::unique(a1,a1+n,
[](float a, float b)
{
return std::fabs(a-b) < 10e-9;
}
) - a1;
?
Live demo link
What I'm trying to achieve is to take the average of the numbers stored in the array and find the number which is closest to it.
My code compiles, but has an error just after starting. I think it's something to do with the memory handling (I don't feel confident with pointers, etc. yet)
Could some nice guy take a look at my code and tell me what's wrong with it? (don't be hard on me, I'm a beginner)
#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;
}
The following
double* m = 0;
sets m to the null pointer. Any attempt to dereference it will result in undefined behaviour.
Change the above to:
double m = 0;
and replace *m with m everywhere, also changing the function's return type to just double.
Finally, you don't need the tmp array.
1 What's wrong with your code? The use of pointers and the resulting beginner errors.
2 How to compute the average in C++? Roughly like this:
#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;
}
(note: compile with option -std=c++11)
3 How to find the number closest to it (the average)? If your computer is IEEE compliant (most are but some compiler optimisations violate that), the result of any arithmetic is rounded to the closest representable number. So, nothing special needs to be done here. However, accumulation of numbers is subject to round-off error and hence loss of precision. This can be minimised by accumulating the numbers in descending order of their absolute value, though there exist pathological cases where the computed accumulation is still rather imprecise. Find out more on, say, wikipedia.
4 How to find the array value closest to it (the average)? One way is shown in Johan's answer. However, it unnecessarily alters the array by performing a partial sort. Better use std::min_element
(no need to 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;
building on to the answer by Walter, adding the 'find value closest to average' part:
#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;
}
Alternative (slower) implementation using transform (reduces the number of calls to fabs, but does a copy):
#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)];
}
Using a standard algorithm is usually the right thing to do as it is more maintainable. In this case I did not find a way to use a standard algorithm as fast as this (about 30% faster than the first solution above with 10e7 elements and -O2):
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;