Related
I am stuck on this program as follows:
Write a program that takes as input five numbers and outputs the mean (average) and standard deviation of the numbers. If the numbers are x1,x2,x3,x4,x5.
To solve mean : mean = (x1 + x2 + x3 + x4 + x5) / 5;
To solve deviation:
deviation = sqrt((pow(x1 - x, 2) + pow(x2 - x, 2) + pow(x3 - x, 2) + pow(x4 - x, 2) + pow(x5 - x, 2)) / 5);
Your program must contain at least the following functions: a function that calculates and returns the mean and a function that calculates the standard deviation.
I am trying to use variable x1,x2,x3,x4,x5 from main but I am getting unitialized local variable errors and can not compile it.
#include <iostream>
#include <cmath>
using namespace std;
// Named constant definitions (and function declarations):
//Prototype
double meanfn();
double deviationfn();
// Main program:
int main()
{
// Variable declarations:
double x1, x2, x3, x4, x5;
// Function body:
cout << "Enter a number followed by space 5 times to calculate the mean of five numbers. " << endl;
cin >> x1 >> x2 >> x3 >> x4 >> x5;
return 0;
} // end function main
double meanfn()
{
double x1, x2, x3, x4, x5;
double mean;
mean = (x1 + x2 + x3 + x4 + x5) / 5;
return mean;
}// end function meanfn
double deviationfn(double mean)
{
double x,deviation;
double x1, x2, x3, x4, x5;
x = mean;
deviation = sqrt((pow(x1 - x, 2) + pow(x2 - x, 2) + pow(x3 - x, 2) + pow(x4 - x, 2) + pow(x5 - x, 2)) / 5);
return deviation;
}
You have two problems of understanding basics in C++:
Variable scope.
Function parameters.
To briefly explain:
Variables in C++ live only in the scope they were declared in. In your case, you declared: x1, x2, x3, x4, x5 inside of the function main which means they do not exist outside that scope. The variables x1, x2, x3, x4, x5 in meanfn and deviationfn are completely different variables. They only share the same names and that's about it. Therefore, when you declared them inside the functions, they had no previously assigned values which means you cannot use them.
As for function parameters, you have to declare what parameters a function accepts in its signature. Your meanfn signature is double meanfn() which accepts no parameters. If you want it to accept 5 and only 5 double variables, you should change it to accommodate.
There are two solutions based on the explanations above:
#include <iostream>
#include <cmath>
using namespace std;
// Named constant definitions (and function declarations):
//Prototype
double meanfn();
double deviationfn();
// Main program:
// Variable declarations:
double x1, x2, x3, x4, x5; // outside of 'main' making them global and everything has access to these variables.
int main()
{
// Function body:
cout << "Enter a number followed by space 5 times to calculate the mean of five numbers. " << endl;
cin >> x1 >> x2 >> x3 >> x4 >> x5;
// CALL YOUR FUNCTIONS, THEY WONT BE CALLED BY THEIR OWN
double mean = meanfn();
double deviation = deviationfn(mean);
// print results
std::cout << "\n Mean: " << mean << "\n Deviation: " << deviation;
return 0;
} // end function main
double meanfn()
{
double mean = (x1 + x2 + x3 + x4 + x5) / 5;
return mean;
}// end function meanfn
double deviationfn(double mean)
{
double x,deviation;
x = mean;
deviation = sqrt((pow(x1 - x, 2) + pow(x2 - x, 2) + pow(x3 - x, 2) + pow(x4 - x, 2) + pow(x5 - x, 2)) / 5);
return deviation;
}
In the solution above, the variables x1, x2, x3, x4, x5 were moved to be global variables making their access global and hence all functions can use them.
The second solution would consider parameter passing for the functions, such as:
#include <iostream>
#include <cmath>
using namespace std;
// Named constant definitions (and function declarations):
//Prototype
double meanfn(double x1, double x2, double x3, double x4, double x5);
double deviationfn(double mean, double x1, double x2, double x3, double x4, double x5);
// Main program:
int main()
{
// Variable declarations:
double x1, x2, x3, x4, x5;
// Function body:
cout << "Enter a number followed by space 5 times to calculate the mean of five numbers. " << endl;
cin >> x1 >> x2 >> x3 >> x4 >> x5;
// see the difference in the function calls?
double mean = meanfn(x1, x2, x3, x4, x5);
double deviation = deviationfn(mean, x1, x2, x3, x4, x5);
// print results
std::cout << "\n Mean: " << mean << "\n Deviation: " << deviation;
return 0;
} // end function main
double meanfn(double x1, double x2, double x3, double x4, double x5)
{
double mean;
mean = (x1 + x2 + x3 + x4 + x5) / 5;
return mean;
}// end function meanfn
double deviationfn(double mean, double x1, double x2, double x3, double x4, double x5)
{
double x,deviation;
x = mean;
deviation = sqrt((pow(x1 - x, 2) + pow(x2 - x, 2) + pow(x3 - x, 2) + pow(x4 - x, 2) + pow(x5 - x, 2)) / 5);
return deviation;
}
Rather than having 5 variables with numbered names, you can instead have one variable that contains all 5.
#include <iostream>
#include <cmath>
#include <array>
using Values = std::array<double, 5>;
double mean(Values xs)
{
return (xs[0] + xs[1] + xs[2] + xs[3] + xs[4]) / xs.size();
}
double distribution(Values xs, double x_bar)
{
return sqrt((pow(xs[0] - x_bar, 2) + pow(xs[1] - x_bar, 2) + pow(xs[2] - x_bar, 2) + pow(xs[3] - x_bar, 2) + pow(xs[4] - x_bar, 2)) / xs.size());
}
int main()
{
std::cout << "Enter a number followed by space 5 times to calculate the mean of five numbers. " << std::endl;
Values xs;
std::cin >> xs[0] >> xs[1] >> xs[2] >> xs[3] >> xs[4];
auto x_bar = mean(xs);
auto sigma = distribution(xs, x_bar);
std::cout << "\n Mean: " << x_bar << "\n Deviation: " << sigma;
}
But notice that each of those functions is doing the same operation to each of the values, then performing some final calculation based on how many. That can better be expressed using functions from <algorithm>. We then don't need to know how many elements there are.
#include <algorithm>
#include <vector>
using Values = std::vector<double>; // Any number of values
double mean(Values xs)
{
// The default combiner is +
return std::accumulate(xs.begin(), xs.end(), 0) / xs.size();
}
double distribution(Values xs, double x_bar)
{
auto sum_squares = [x_bar](double cumulative, double x){ return cumulative + pow(x - x_bar, 2); }
return sqrt(std::accumulate(xs.begin(), xs.end(), 0, sum_squares) / xs.size());
}
In c++11 I have functions
double f(double x1);
double f(double x1, double x2);
double f(double x1, double x2, double x3);
double h(double x);
I also have functions
double g(std::vector<double> y, double x1);
double g(std::vector<double> y, double x1, double x2);
double g(std::vector<double> y, double x1, double x2, double x3);
The implementation of g is something like
double g(std::vector<double> y, double x1, double x2, double x3)
{
double ans = 0.0;
for(g : y)
{
ans = h(g) * f(x1, x2, x3);
}
return ans;
}
Is there an elegant (templated) way of doing this instead of writing g 3 times with overloaded arguments?
template<typename... Ts>
double g(std::vector<double> v, Ts&&...ts ) {
double ret = 1;
for(auto x:v){
ret *= h(x)*f(ts...);
}
return ret;
}
if you want to restrict the ts to be doubles beyond calling f, it needs more work. Otherwise, the above is enough.
(Note the resriction work gets prettier in C++1y with concepts lite: in C++11 I vote to skip the restriction of Ts to doubles, and just rely on f only taking doubles.)
I have a particle system and I am using boost::geometry to approximate my elliptical particles as polygons and then use the intersection function of the library to find the overlap area. I am calculating an "inner" and "outer" ellipse(polygon) area to assign a "potential" for each particle-particle interaction.
My potential function is this:
double Potential(Cell* current, Cell* next)
{
double areaRep, areaAtt;
double distance = Distance(current,next);
double A1 = current->getLength();
double B1 = A1/2.0;
double theta1 = current->getTheta(); //*180.0/M_PI
double x1 = current->getCurrX();
double y1 = current->getCurrY();
double A2 = next->getLength();
double B2 = A2/2.0;
double theta2 = next->getTheta();
double x2 = next->getCurrX();
double y2 = next->getCurrY();
polygon_2d poly1, poly2, poly3, poly4;
double lamda1, lamda2;
lamda1 = 0.0005; lamda2 = 0.00001;
if(distance < 2.0*1.5*A1) {
ellipse2poly(theta1, A1, B1, x1, y1, &poly1);
ellipse2poly(theta2, A2, B2, x2, y2, &poly2);
areaRep = getOverlapingAreaPoly(poly1,poly2);
ellipse2poly(theta1, 1.5*A1, 1.5*B1, x1, y1, &poly3);
ellipse2poly(theta2, 1.5*A2, 1.5*B2, x2, y2, &poly4);
areaAtt = getOverlapingAreaPoly(poly3, poly4);
return (lamda1*areaRep - lamda2*areaAtt);
}
else
return 0.0;
}
The "polygonizing" function is:
int ellipse2poly(double theta, double A1, double B1, double H1, double K1, polygon_2d *po)
{
using namespace boost::geometry;
polygon_2d poly;
const int n = 20;
double angle = theta; // cell orientation
double a = A1; // Long semi-axis length
double b = B1; // short semi-axis length
double xc = H1; // current X position
double yc = K1; // current Y position
if(!n)
{
std::cout << "error ellipse(): n should be >0\n" <<std::endl;
return 0;
}
double t = 0;
int i = 0;
double coor[2*n+1][2];
double x, y;
double step = M_PI/(double)n;
double sinphi = sin(angle);
double cosphi = cos(angle);
for(i=0; i<2*n+1; i++)
{
x = xc + a*cos(t)*cosphi - b*sin(t)*sinphi;
y = yc + a*cos(t)*sinphi + b*sin(t)*cosphi;
coor[i][0] = x;
coor[i][1] = y;
t += step;
}
assign_points(poly, coor);
correct(poly);
*po = poly;
return 1;
}
And the returned area is:
double getOverlapingAreaPoly(polygon_2d poly, polygon_2d poly2)
{
point_2d cent; //centre of overlaping area
double overAreaPoly = 0.0;
typedef std::vector<polygon_2d > polygon_list;
polygon_list v;
intersection(poly,poly2,v);
for (polygon_list::const_iterator it = v.begin(); it != v.end(); ++it)
{
centroid(*it, cent);
overAreaPoly = area(*it);
}
return overAreaPoly;
}
The function is called for every cell (particle) as long as it is not for the same one. Previously, using another method, one iteration of my algorithm would take approximately 43 ms for one iteration for 100 particles. Now it takes approximately 1 min(!!!), so I guess I have done something horribly wrong!
I have tested this only in MSVC2012 under win7 64bit. I will report back for Linux Mint with Qt 4.7.4.
EDIT:
I have tested on Linux Mint with Qt 4.7.4 and it is running very reasonably; maybe 90-100 ms per iteration which is fine. I don't know what is wrong in win7...
I have actually fixed it. I started a new project in Visual Studio and copied all source and header files, recompiled and everything runs smoothly now. I guess radically changing code and adding / subtracting stuff must have some impact...
I have the below class that yields this error for the lines I commented: Description Invalid arguments 'Candidates are:
Eigen::Matrix Forward_Euler(double ()(double), double ()(double), double (*)(double))' I'm getting confused when trying to search for a solution.
The signature for Forward Euler is:
Eigen::MatrixXd Forward_Euler(double (*f)(double), double (*gleft)(double), double (*gright)(double))
And my class is:
class C
{
protected:
A x;
B y;
double a;
double b;
Eigen::MatrixXd u;
public:
double f(double x)
{
return a;
}
double gleft(double tau)
{
return b
}
double gright(double tau)
{
return a*b;
}
FD_Euro_Put(): x(), y(), a(0), b(0){}
FD_Euro_Put(char y1, double y2, double y3, double y4, double x2,
double x3, double x4, double x5, double x6, double x7):
x(x1, x2, x3, x4, x5, x6, x7)
{
double Xleft = x1*x2;
double Xright = x1*x3;
double Tauf = x1*x1;
double NN = floor((x1/x2);
a = x1*x2 - 0.5;
b = x1*x2 + 0.5;
pde = HeatPDE(y1, NN, Xleft, Xright, Tauf, Alpha); //begin problem area
u.resize(pde.N+1, pde.M+1);
if(fdtype == 'f')
u = pde.Forward_Euler(&f, &gleft, &gright);
else if(fdtype == 'b')
u = pde.Backward_Euler(&f, &gleft, &gright);
else if(fdtype == 'c')
u = pde.Crank_Nicolson(&f, &gleft, &gright); //end problem area
else
cout << "Incorrect choice for finite difference type!" << endl;
}
Member function pointers and function pointers are not the same thing. Member function pointers have a much more difficult job and need to deal with things like virtual functions and the this pointer.
But look at the functions in your class! They are not really object functions because they use nothing from the object. You can either move them out of the class or make them static functions of the class. If you do either of those things you can use them as function pointers.
I think you have to use a class template and static functions. You can provide the arguments as template arguments.
I've started refactoring some legacy code recently and came across two functions for drawing a coordinate grid, the problem is that these functions differ only in orthogonal variables they treat, something like that
void DrawScaleX(HDC dc, int step, int x0, int x1, int y0, int y1)
{
for(int x = x0; x < x1; x += step)
{
MoveToEx(dc, x, y0, NULL);
LineTo(dc, x, y1);
}
}
void DrawScaleY(HDC dc, int step, int x0, int x1, int y0, int y1)
{
for(int y = y0; y < y1; y += step)
{
MoveToEx(dc, x0, y, NULL);
LineTo(dc, x1, y);
}
}
So if I decide to add some fancy stuff, like antialiasing or merely change drawing pencil or whatever I'll have to put the same code in both of them and it's code duplication and it's bad we all know why.
My question is how would you rewrite these two functions into a single one to avoid this problem?
Why you just do not extract the body of the for cycle into a separate function? Then you can do the funny stuff in the extracted function.
void DrawScaleX(HDC dc, int step, int x0, int x1, int y0, int y1)
{
for(int x = x0; x < x1; x += step)
{
DrawScale(dc, x, y0, x, y1);
}
}
void DrawScaleY(HDC dc, int step, int x0, int x1, int y0, int y1)
{
for(int y = y0; y < y1; y += step)
{
DrawScale(dc, x0, y, x1, y);
}
}
private void DrawScale(HDC dc, int x0, int y0, int x1, int y1)
{
//Add funny stuff here
MoveToEx(dc, x0, y0, NULL);
LineTo(dc, x1, y1);
//Add funny stuff here
}
Drawing a line is simply joining two points, and drawing a scaling incrementing (x0,y0) and(x1,y1) in a particular direction, through X, and/or through Y.
This boils down to, in the scale case, which direction(s) stepping occurs (maybe both directions for fun).
template< int XIncrement, YIncrement >
struct DrawScale
{
void operator()(HDC dc, int step, int x0, int x1, int y0, int y1)
{
const int deltaX = XIncrement*step;
const int deltaY = YIncrement*step;
const int ymax = y1;
const int xmax = x1;
while( x0 < xmax && y0 < ymax )
{
MoveToEx(dc, x0, y0, NULL);
LineTo(dc, x1, y1);
x0 += deltaX;
x1 += deltaX;
y0 += deltaY;
y1 += deltaY;
}
}
};
typedef DrawScale< 1, 0 > DrawScaleX;
typedef DrawScale< 0, 1 > DrawScaleY;
The template will do its job: at compile time the compiler will remove all the null statements i.e. deltaX or deltaY is 0 regarding which function is called and half of the code goes away in each functor.
You can add you anti-alias, pencil stuff inside this uniq function and get the code properly generated generated by the compiler.
This is cut and paste on steroids ;-)
-- ppi
Here is my own solution
class CoordGenerator
{
public:
CoordGenerator(int _from, int _to, int _step)
:from(_from), to(_to), step(_step), pos(_from){}
virtual POINT GetPoint00() const = 0;
virtual POINT GetPoint01() const = 0;
bool Next()
{
if(pos > step) return false;
pos += step;
}
protected:
int from;
int to;
int step;
int pos;
};
class GenX: public CoordGenerator
{
public:
GenX(int x0, int x1, int step, int _y0, int _y1)
:CoordGenerator(x0, x1, step),y0(_y0), y1(_y1){}
virtual POINT GetPoint00() const
{
const POINT p = {pos, y0};
return p;
}
virtual POINT GetPoint01() const
{
const POINT p = {pos, y1};
return p;
}
private:
int y0;
int y1;
};
class GenY: public CoordGenerator
{
public:
GenY(int y0, int y1, int step, int _x0, int _x1)
:CoordGenerator(y0, y1, step),x0(_x0), x1(_x1){}
virtual POINT GetPoint00() const
{
const POINT p = {x0, pos};
return p;
}
virtual POINT GetPoint01() const
{
const POINT p = {x1, pos};
return p;
}
private:
int x1;
int x0;
};
void DrawScale(HDC dc, CoordGenerator* g)
{
do
{
POINT p = g->GetPoint00();
MoveToEx(dc, p.x, p.y, 0);
p = g->GetPoint01();
LineTo(dc, p.x, p.y);
}while(g->Next());
}
But I it seems to me too complicated for such a tiny problem, so I'm looking forward to still see your solutions.
Well, an obvious "solution" would be to make a single function and add one extra parameter (of enum-like type). And then do an if() or switch() inside, and perform the appropriate actions. Because hey, the functionality of the functions is different, so you have to do those different actions somewhere.
However, this adds runtime complexity (check things at runtime) in a place that could be just better checked at compile time.
I don't understand what's the problem in adding extra parameters in the future in both (or more functions). It goes like this:
add more parameters to all functions
compile your code, it won't compile in a bunch of places because it does not pass new parameters.
fix all places that call those functions by passing new parameters.
profit! :)
If it's C++, of course you could make the function be a template, and instead adding an extra parameter, you add a template parameter, and then specialize template implementations to do different things. But this is just obfuscating the point, in my opinion. Code becomes harder to understand, and the process of extending it with more parameters is still exactly the same:
add extra parameters
compile code, it won't compile in a bunch of places
fix all places that call that function
So you've won nothing, but made code harder to understand. Not a worthy goal, IMO.
I think I'd move:
MoveToEx(dc, x0, y, NULL);
LineTo(dc, x1, y);
into their own function DrawLine(x0,y0,x0,y0), which you can call from each of the existing functions.
Then there's one place to add extra drawing effects?
A little templates... :)
void DrawLine(HDC dc, int x0, int y0, int x0, int x1)
{
// anti-aliasing stuff
MoveToEx(dc, x0, y0, NULL);
LineTo(dc, x1, y1);
}
struct DrawBinderX
{
DrawBinderX(int y0, int y1) : y0_(y0), y1_(y1) {}
void operator()(HDC dc, int i)
{
DrawLine(dc, i, y0_, i, y1_);
}
private:
int y0_;
int y1_;
};
struct DrawBinderY
{
DrawBinderX(int x0, int x1) : x0_(x0), x1_(x1) {}
void operator()(HDC dc, int i)
{
DrawLine(dc, x0_, i, x1_, i);
}
private:
int x0_;
int x1_;
};
template< class Drawer >
void DrawScale(Drawer drawer, HDC dc, int from, int to, int step)
{
for (int i = from; i < to; i += step)
{
drawer(dc, i);
}
}
void DrawScaleX(HDC dc, int step, int x0, int x1, int y0, int y1)
{
DrawBindexX drawer(y0, y1);
DrawScale(drawer, dc, x0, x1, step);
}
void DrawScaleY(HDC dc, int step, int x0, int x1, int y0, int y1)
{
DrawBindexY drawer( x0, x1 );
DrawScale(drawer, dc, y0, y1, step);
}