chapter 15 functions and graphing bjarne stroustrup
TRANSCRIPT
Chapter 15Chapter 15 Functions and graphing Functions and graphing
Bjarne Stroustrup Bjarne Stroustrup www.stroustrup.com/Programmingwww.stroustrup.com/Programming
AbstractAbstract Here we present ways of graphing functions Here we present ways of graphing functions
and data and some of the programming and data and some of the programming techniques needed to do so, notably scaling. techniques needed to do so, notably scaling.
Stroustrup/ProgrammingStroustrup/Programming 22
NoteNote This course is about programmingThis course is about programming
The examples – such as graphics – are simply examples ofThe examples – such as graphics – are simply examples of Useful programming techniquesUseful programming techniques Useful tools for constructing real programsUseful tools for constructing real programs
Look for the way the examples are constructedLook for the way the examples are constructed How are “big problems” broken down into little ones and solved How are “big problems” broken down into little ones and solved
separately?separately? How are classes defined and usedHow are classes defined and used
Do they have sensible data members? Do they have sensible data members? Do they have useful member functions?Do they have useful member functions?
Use of variablesUse of variables Are there too few?Are there too few? Too many?Too many? How would you have named them better?How would you have named them better?
Stroustrup/ProgrammingStroustrup/Programming 33
Graphing functionsGraphing functions
Start with something really simpleStart with something really simple Always remember “Hello, World!”Always remember “Hello, World!”
We graph functions of one argument yielding a one valueWe graph functions of one argument yielding a one value Plot (x, f(x)) for values of x in some range [r1,r2)Plot (x, f(x)) for values of x in some range [r1,r2)
Let’s graph three simple functionsLet’s graph three simple functionsdouble one(double x) { return 1; } double one(double x) { return 1; } // // y==1 y==1
double slope(double x) { return x/2; }double slope(double x) { return x/2; } // // y==x/2y==x/2
double square(double x) { return x*x; } double square(double x) { return x*x; } // // y==x*xy==x*x
Stroustrup/ProgrammingStroustrup/Programming 44
FunctionsFunctions
double one(double x) { return 1; } double one(double x) { return 1; } // // y==1y==1
double slope(double x) { return x/2; }double slope(double x) { return x/2; } // // y==x/2y==x/2
double square(double x) { return x*x; } double square(double x) { return x*x; } // // y==x*xy==x*x
Stroustrup/ProgrammingStroustrup/Programming 55
How do we write code to do this?How do we write code to do this?
Simple_window win0(Point(100,100),xmax,ymax,"Function graphing");Simple_window win0(Point(100,100),xmax,ymax,"Function graphing");
Function s(one,-10,11,orig,n_points,x_scale,y_scale); Function s(one,-10,11,orig,n_points,x_scale,y_scale); Function s2(slope,-10,11,orig,n_points,x_scale,y_scale); Function s2(slope,-10,11,orig,n_points,x_scale,y_scale); Function s3(square,-10,11,orig,n_points,x_scale,y_scale); Function s3(square,-10,11,orig,n_points,x_scale,y_scale);
win0.attach(s);win0.attach(s);win0.attach(s2);win0.attach(s2);win0.attach(s3);win0.attach(s3);
win0.wait_for_button( );win0.wait_for_button( );
Stroustrup/ProgrammingStroustrup/Programming 66
Function to be graphed
Range in which to graph
“stuff” to make the graph fit into the window
We need some ConstantsWe need some Constants
const int xmax = 600;const int xmax = 600; // // window sizewindow sizeconst int ymax = 400;const int ymax = 400;
const int x_orig = xmax/2; const int x_orig = xmax/2; const int y_orig = ymax/2;const int y_orig = ymax/2;const Point orig(x_orig, y_orig); const Point orig(x_orig, y_orig); // // position of (0,0) in windowposition of (0,0) in window
const int r_min = -10;const int r_min = -10; // // range [-10:11) == [-10:10] of xrange [-10:11) == [-10:10] of xconst int r_max = 11;const int r_max = 11;
const int n_points = 400;const int n_points = 400; // // number of points used in rangenumber of points used in range
const int x_scale = 20;const int x_scale = 20; // // scaling factorsscaling factors
const int y_scale = 20;const int y_scale = 20;
// // Choosing a center (0,0), scales, and number of points can be fiddlyChoosing a center (0,0), scales, and number of points can be fiddly
// // The range usually comes from the definition of what you are doingThe range usually comes from the definition of what you are doing
Stroustrup/ProgrammingStroustrup/Programming 77
Functions – but what does it mean?Functions – but what does it mean?
What’s wrong with this?What’s wrong with this? No axes (no scale)No axes (no scale) No labelsNo labels
Stroustrup/ProgrammingStroustrup/Programming 88
Label the functionsLabel the functions
Text ts(Point(100,y_orig-30),"one");Text ts(Point(100,y_orig-30),"one");Text ts2(Point(100,y_orig+y_orig/2-10),"x/2");Text ts2(Point(100,y_orig+y_orig/2-10),"x/2");Text ts3(Point(x_orig-90,20),"x*x");Text ts3(Point(x_orig-90,20),"x*x");
Stroustrup/ProgrammingStroustrup/Programming 99
Add x-axis and y-axisAdd x-axis and y-axis
We can use axes to show (0,0) and the scaleWe can use axes to show (0,0) and the scaleAxis x(Axis::x, Point(20,y_orig), xlength/x_scale, "one notch == 1 ");Axis x(Axis::x, Point(20,y_orig), xlength/x_scale, "one notch == 1 ");
Axis y(Axis::y, Point(x_orig, ylength+20, ylength/y_scale, "one notch == 1");Axis y(Axis::y, Point(x_orig, ylength+20, ylength/y_scale, "one notch == 1");
Stroustrup/ProgrammingStroustrup/Programming 1010
Use color (in moderation)Use color (in moderation)
s.set_color(Color::green); s.set_color(Color::green); x.set_color(Color::red);x.set_color(Color::red);
y.set_color(Color::red); y.set_color(Color::red); ts.set_color(Color::green);ts.set_color(Color::green);
Stroustrup/ProgrammingStroustrup/Programming 1111
The implementation of FunctionThe implementation of Function We need a type for the argument specifying the function We need a type for the argument specifying the function
to graphto graph typedef typedef can be used to declare a new name for a typecan be used to declare a new name for a type
typedef int Color;typedef int Color; // // now Color means intnow Color means int
Define the type of our desired argument, Define the type of our desired argument, FctFct typedef double Fct(double);typedef double Fct(double); // // now Fct means functionnow Fct means function
//// taking a double taking a double argumentargument
//// and returning a double and returning a double
Examples of functions of type Examples of functions of type FctFct::double one(double x) { return 1; } double one(double x) { return 1; } // // y==1y==1double slope(double x) { return x/2; }double slope(double x) { return x/2; } // // y==x/2y==x/2double square(double x) { return x*x; } double square(double x) { return x*x; } // // y==x*xy==x*x
Stroustrup/ProgrammingStroustrup/Programming 1212
Now Define “Function”Now Define “Function”
struct Function : Shape struct Function : Shape // // Function is derived from ShapeFunction is derived from Shape{{
// // all it needs is a constructor:all it needs is a constructor:Function(Function(
Fct f,Fct f, // // f f is ais a Fct Fct (takes a double, returns a double) (takes a double, returns a double)
double r1, double r1, // // the range of x values (arguments to f) [r1:r2)the range of x values (arguments to f) [r1:r2)double r2,double r2,Point orig,Point orig, // // the screen location of (0,0)the screen location of (0,0)int count,int count, // // number of points used to draw the functionnumber of points used to draw the function
// // (number of line segments used is count-1)(number of line segments used is count-1)
double xscale , double xscale , //// the locationthe location (x,f(x)) (x,f(x)) is is (xscale*x,yscale*f(x)) (xscale*x,yscale*f(x)) double yscale double yscale
); );
};};Stroustrup/ProgrammingStroustrup/Programming 1313
Implementation of FunctionImplementation of Function
Function::Function( Fct f,Function::Function( Fct f,double r1, double r2,double r1, double r2, // // rangerangePoint xy,Point xy,int count,int count,double xscale, double yscale )double xscale, double yscale )
{{if (r2-r1<=0) error("bad graphing range");if (r2-r1<=0) error("bad graphing range");if (count <=0) error("non-positive graphing count");if (count <=0) error("non-positive graphing count");double dist = (r2-r1)/count;double dist = (r2-r1)/count;double r = r1;double r = r1;for (int i = 0; i<count; ++i) {for (int i = 0; i<count; ++i) {
add(Point(xy.x+int(r*xscale), xy.y-int(f(r)*yscale)));add(Point(xy.x+int(r*xscale), xy.y-int(f(r)*yscale)));r += dist;r += dist;
}}}}
Stroustrup/ProgrammingStroustrup/Programming 1414
Default argumentsDefault arguments Seven arguments are too many!Seven arguments are too many!
Many too manyMany too many We’re just asking for confusion and errorsWe’re just asking for confusion and errors Provide defaults for some (trailing) argumentsProvide defaults for some (trailing) arguments
Default arguments are often useful for constructorsDefault arguments are often useful for constructors
struct Function : Shape {struct Function : Shape {Function( Fct f, double r1, double r2,Function( Fct f, double r1, double r2, Point xy,Point xy,
int count = 100,int count = 100, double xscale = 25, double yscale=25 );double xscale = 25, double yscale=25 );};};
Function f1(sqrt, 0, 11, orig, 100, 25, 25 );Function f1(sqrt, 0, 11, orig, 100, 25, 25 ); // // ok (obviously)ok (obviously)Function f2(sqrt, 0, 11, orig, 100, 25);Function f2(sqrt, 0, 11, orig, 100, 25); // // ok: exactly the same as f1ok: exactly the same as f1Function f3(sqrt, 0, 11, orig, 100);Function f3(sqrt, 0, 11, orig, 100); // // ok: exactly the same as f1ok: exactly the same as f1Function f4(sqrt, 0, 11, orig);Function f4(sqrt, 0, 11, orig); // // ok: exactly the same as f1ok: exactly the same as f1
Stroustrup/ProgrammingStroustrup/Programming 1515
FunctionFunction Is Is FunctionFunction a “pretty class”? a “pretty class”?
NoNo Why not?Why not?
What could you do with all of those position and scaling What could you do with all of those position and scaling arguments?arguments?
See 15.6.3 for one minor ideaSee 15.6.3 for one minor idea
If you can’t do something genuinely clever, do something If you can’t do something genuinely clever, do something simple, so that the user can do anything neededsimple, so that the user can do anything needed
Such as adding parameters so that the caller can controlSuch as adding parameters so that the caller can control
Stroustrup/ProgrammingStroustrup/Programming 1616
Some more functionsSome more functions#include<cmath>#include<cmath> // // standard mathematical functionsstandard mathematical functions
// // You can combine functions (e.g., by addition):You can combine functions (e.g., by addition):
double sloping_cos(double x) { return cos(x)+slope(x); }double sloping_cos(double x) { return cos(x)+slope(x); }
Function s4(cos,-10,11,orig,400,20,20);Function s4(cos,-10,11,orig,400,20,20);
s4.set_color(Color::blue);s4.set_color(Color::blue);
Function s5(sloping_cos,-10,11,orig,400,20,20);Function s5(sloping_cos,-10,11,orig,400,20,20);
Stroustrup/ProgrammingStroustrup/Programming 1717
Cos and sloping-cosCos and sloping-cos
Stroustrup/ProgrammingStroustrup/Programming 1818
Standard mathematical functions Standard mathematical functions (<cmath>)(<cmath>)
double abs(double);double abs(double); // // absolute valueabsolute value
double ceil(double d);double ceil(double d); // // smallest integersmallest integer >= d >= d double floor(double d);double floor(double d); // // largest integerlargest integer <= d <= d
double sqrt(double d);double sqrt(double d); // // d d must be non-negativemust be non-negative
double cos(double);double cos(double); double sin(double);double sin(double); double tan(double);double tan(double); double acos(double);double acos(double); // // result is non-negative; “a” for “arc”result is non-negative; “a” for “arc” double asin(double);double asin(double); // // result nearest to 0 returnedresult nearest to 0 returned double atan(double);double atan(double); double sinh(double);double sinh(double); // // “h” for “hyperbolic”“h” for “hyperbolic” double cosh(double);double cosh(double); double tanh(double);double tanh(double);
Stroustrup/ProgrammingStroustrup/Programming 1919
Standard mathematical functions Standard mathematical functions (<cmath>)(<cmath>)
double exp(double);double exp(double); // // base ebase e double log(double d);double log(double d); // // natural logarithm (basenatural logarithm (base e)e) ; d ; d must be positivemust be positive double log10(double);double log10(double); // // base 10 logarithmbase 10 logarithm
double pow(double x, double y);double pow(double x, double y); // // x x to the power ofto the power of y y double pow(double x, int y);double pow(double x, int y); // // x x to the power ofto the power of y y double atan2(double x, double y);double atan2(double x, double y); // // atan(x/y)atan(x/y) double fmod(double d, double m);double fmod(double d, double m); // // floating-point remainder floating-point remainder
// // same sign as d%msame sign as d%m double ldexp(double d, int i);double ldexp(double d, int i); // // d*pow(2,i)d*pow(2,i)
Stroustrup/ProgrammingStroustrup/Programming 2020
Why graphing?Why graphing?
Because you can see things in a graph that are not obvious from Because you can see things in a graph that are not obvious from a set of numbersa set of numbers How would you understand a sine curve if you couldn’t (ever) see one? How would you understand a sine curve if you couldn’t (ever) see one?
Visualization isVisualization is key to understanding in many fieldskey to understanding in many fields Used in most research and business areasUsed in most research and business areas
Science, medicine, business, telecommunications, control of large systemsScience, medicine, business, telecommunications, control of large systems
Stroustrup/ProgrammingStroustrup/Programming 2121
An example: An example: eexx
eexx == 1 == 1 + x + x
+ x+ x22/2!/2!+ x+ x33/3!/3!
+ x+ x44/4!/4!+ x+ x55/5!/5!
+ x+ x66/6!/6!+ x+ x77/7! /7!
+ + ……
Where ! Means factorial (e.g. 4!==4*3*2*1)Where ! Means factorial (e.g. 4!==4*3*2*1)
Stroustrup/ProgrammingStroustrup/Programming 2222
Simple algorithm to approximate eSimple algorithm to approximate exx
double fac(int n) { /* double fac(int n) { /* …… */ } */ } // // factorialfactorial
double term(double x, int n) double term(double x, int n) // // xxnn/n!/n!
{{
return pow(x,n)/fac(n);return pow(x,n)/fac(n);
}}
double expe(double x, int n)double expe(double x, int n) // // sum of n terms of xsum of n terms of x
{{
double sum = 0;double sum = 0;
for (int i = 0; i<n; ++i) sum+=term(x,i);for (int i = 0; i<n; ++i) sum+=term(x,i);
return sum;return sum;
}}
Stroustrup/ProgrammingStroustrup/Programming 2323
Simple algorithm to approximate eSimple algorithm to approximate exx
But we can only graph functions of one argument, so how can we But we can only graph functions of one argument, so how can we get graph get graph expe(x,n)expe(x,n) for various for various nn??
int expN_number_of_terms = 6;int expN_number_of_terms = 6; // // nasty sneaky argument to expNnasty sneaky argument to expN
double expN(double x) double expN(double x) // // sum of expN_number_of_terms terms of xsum of expN_number_of_terms terms of x
{{
return expe(x,expN_number_of_terms);return expe(x,expN_number_of_terms);
}}
Stroustrup/ProgrammingStroustrup/Programming 2424
““Animate” approximations to eAnimate” approximations to exx
Simple_window win(Point(100,100),xmax,ymax,"");Simple_window win(Point(100,100),xmax,ymax,"");// // the real exponential :the real exponential :Function real_exp(exp,r_min,r_max,orig,200,x_scale,y_scale);Function real_exp(exp,r_min,r_max,orig,200,x_scale,y_scale);real_exp.set_color(Color::blue);real_exp.set_color(Color::blue);win.attach(real_exp);win.attach(real_exp);
const int xlength = xmax-40;const int xlength = xmax-40;const int ylength = ymax-40;const int ylength = ymax-40;Axis x(Axis::x, Point(20,y_orig),Axis x(Axis::x, Point(20,y_orig),
xlength, xlength/x_scale, "one notch == 1");xlength, xlength/x_scale, "one notch == 1");Axis y(Axis::y, Point(x_orig,ylength+20),Axis y(Axis::y, Point(x_orig,ylength+20),
ylength, ylength/y_scale, "one notch == 1");ylength, ylength/y_scale, "one notch == 1");
win.attach(x);win.attach(x);win.attach(y);win.attach(y);x.set_color(Color::red);x.set_color(Color::red);y.set_color(Color::red);y.set_color(Color::red);
Stroustrup/ProgrammingStroustrup/Programming 2525
““Animate” approximations to eAnimate” approximations to exx
for (int n = 0; n<50; ++n) {for (int n = 0; n<50; ++n) {
ostringstream ss;ostringstream ss;
ss << "exp approximation; n==" << n ;ss << "exp approximation; n==" << n ;
win.set_label(ss.str().c_str());win.set_label(ss.str().c_str());
expN_number_of_terms = n;expN_number_of_terms = n; // // nasty sneaky argument to expNnasty sneaky argument to expN
// // next approximation:next approximation:
Function e(expN,r_min,r_max,orig,200,x_scale,y_scale); Function e(expN,r_min,r_max,orig,200,x_scale,y_scale);
win.attach(e);win.attach(e);
wait_for_button();wait_for_button(); // // give the user time to lookgive the user time to look
win.detach(e);win.detach(e);
}}
Stroustrup/ProgrammingStroustrup/Programming 2626
DemoDemo The following screenshots are of the successive The following screenshots are of the successive
approximations of approximations of exp(x) exp(x) using using expe(x,n)expe(x,n)
Stroustrup/ProgrammingStroustrup/Programming 2727
Demo n = 0Demo n = 0
Stroustrup/ProgrammingStroustrup/Programming 2828
Demo n = 1Demo n = 1
Stroustrup/ProgrammingStroustrup/Programming 2929
Demo n = 2Demo n = 2
Stroustrup/ProgrammingStroustrup/Programming 3030
Demo n = 3Demo n = 3
Stroustrup/ProgrammingStroustrup/Programming 3131
Demo n = 4Demo n = 4
Stroustrup/ProgrammingStroustrup/Programming 3232
Demo n = 5Demo n = 5
Stroustrup/ProgrammingStroustrup/Programming 3333
Demo n = 6Demo n = 6
Stroustrup/ProgrammingStroustrup/Programming 3434
Demo n = 7Demo n = 7
Stroustrup/ProgrammingStroustrup/Programming 3535
Demo n = 8Demo n = 8
Stroustrup/ProgrammingStroustrup/Programming 3636
Demo n = 18Demo n = 18
Stroustrup/ProgrammingStroustrup/Programming 3737
Demo n = 19Demo n = 19
Stroustrup/ProgrammingStroustrup/Programming 3838
Demo n = 20Demo n = 20
Stroustrup/ProgrammingStroustrup/Programming 3939
Demo n = 21Demo n = 21
Stroustrup/ProgrammingStroustrup/Programming 4040
Demo n = 22Demo n = 22
Stroustrup/ProgrammingStroustrup/Programming 4141
Demo n = 23Demo n = 23
Stroustrup/ProgrammingStroustrup/Programming 4242
Demo n = 30Demo n = 30
Stroustrup/ProgrammingStroustrup/Programming 4343
Why did the graph “go wild”?Why did the graph “go wild”?
Floating-point numbers are an approximations of real numbersFloating-point numbers are an approximations of real numbers Just approximationsJust approximations Real numbers can be arbitrarily large and arbitrarily smallReal numbers can be arbitrarily large and arbitrarily small
Floating-point numbers are of a fixed sizeFloating-point numbers are of a fixed size Sometimes the approximation is not good enough for what you doSometimes the approximation is not good enough for what you do Here, small inaccuracies (rounding errors) built up into huge errorsHere, small inaccuracies (rounding errors) built up into huge errors
AlwaysAlways be suspicious about calculationsbe suspicious about calculations check your resultscheck your results hope that your errors are obvioushope that your errors are obvious
You want your code to break early – before anyone else gets to use itYou want your code to break early – before anyone else gets to use it
Stroustrup/ProgrammingStroustrup/Programming 4444
Graphing dataGraphing data
Often, what we want to graph is data, not a well-defined mathematical functionOften, what we want to graph is data, not a well-defined mathematical function Here, we used three Here, we used three Open_polylineOpen_polyliness
Stroustrup/ProgrammingStroustrup/Programming 4545
Graphing dataGraphing data
Carefully design your screen layoutCarefully design your screen layoutStroustrup/ProgrammingStroustrup/Programming 4646
Code for AxisCode for Axis
struct Axis : Shape {struct Axis : Shape {enum Orientation { x, y, z };enum Orientation { x, y, z };Axis(Orientation d, Point xy, int length,Axis(Orientation d, Point xy, int length,
int number_of_notches=0,int number_of_notches=0, // // default: no notchesdefault: no notchesstring label = ""string label = "" // // default : no labeldefault : no label););
void draw_lines() const;void draw_lines() const;void move(int dx, int dy);void move(int dx, int dy);
void set_color(Color);void set_color(Color); // // in case we want to change the color of all parts at oncein case we want to change the color of all parts at once
// // line stored in Shapeline stored in Shape//// orientation not stored (can be deduced from line) orientation not stored (can be deduced from line)Text label;Text label;Lines notches;Lines notches;
};};
Stroustrup/ProgrammingStroustrup/Programming 4747
Axis::Axis(Orientation d, Point xy, int length, int n, string lab)Axis::Axis(Orientation d, Point xy, int length, int n, string lab):label(Point(0,0),lab):label(Point(0,0),lab)
{{
if (length<0) error("bad axis length");if (length<0) error("bad axis length");
switch (d){switch (d){
case Axis::x:case Axis::x:
{{ Shape::add(xy);Shape::add(xy); // // axis line beginaxis line begin
Shape::add(Point(xy.x+length,xy.y));Shape::add(Point(xy.x+length,xy.y)); // // axis line endaxis line end
if (1<n) {if (1<n) {
int dist = length/n;int dist = length/n;
int x = xy.x+dist;int x = xy.x+dist;
for (int i = 0; i<n; ++i) {for (int i = 0; i<n; ++i) {
notches.add(Point(x,xy.y),Point(x,xy.y-5));notches.add(Point(x,xy.y),Point(x,xy.y-5));
x += dist;x += dist;
}}
}}
label.move(length/3,xy.y+20); label.move(length/3,xy.y+20); // // put label under the lineput label under the line
break;break;
}}
// …// …
}}Stroustrup/ProgrammingStroustrup/Programming 4848
Axis implementationAxis implementation
void Axis::draw_lines() constvoid Axis::draw_lines() const{{
Shape::draw_lines();Shape::draw_lines(); // // the linethe linenotches.draw_lines();notches.draw_lines(); // // the notches may have a different color from the linethe notches may have a different color from the linelabel.draw(); label.draw(); // // the label may have a different color from the linethe label may have a different color from the line
}}
void Axis::move(int dx, int dy)void Axis::move(int dx, int dy){{
Shape::move(dx,dy);Shape::move(dx,dy); // // the linethe linenotches.move(dx,dy);notches.move(dx,dy);label.move(dx,dy);label.move(dx,dy);
}}
void Axis::set_color(Color c)void Axis::set_color(Color c){{
// // … the obvious three lines …… the obvious three lines …}}
Stroustrup/ProgrammingStroustrup/Programming 4949
Next LectureNext Lecture Graphical user interfacesGraphical user interfaces Windows and WidgetsWindows and Widgets Buttons and dialog boxesButtons and dialog boxes
Stroustrup/ProgrammingStroustrup/Programming 5050