Sequence of Bisect implementations
Bisect7_dc.cpp
Go to the documentation of this file.
1 // Bisect6.cpp
2 // Recursive function
3 // Example: Find the point of zero by bisection
4 
5 // Version 6: All three Bisection functions with the same name
6 // Version 7: now with array of functions
7 // Version 7_dc: try it with a discontinuous function dc(x) ==> segmentation fault, but solved in Bisect(...)
8 //
9 
10 #include <array>
11 #include <cmath>
12 #include <functional> // function; C++11
13 #include <iostream>
14 #include <map>
15 using namespace std;
16 
17 double f(const double x) // declaration and
18 {
19  return sin(x) - 0.5 * x ; // definition of function f(x)
20 }
21 
22 double g(const double x) // declaration and
23 {
24  return -(x - 1.234567) * (x + 0.987654) ; // definition of function g(x)
25 }
26 
27 double h(const double x) // declaration and
28 {
29  return 3.0 - exp(x) ; // definition of function h(x)
30 }
31 
32 double t(const double x) // declaration and
33 {
34  return 1 - x * x ; // definition of function t(x)
35 }
36 
37 double dc(const double x) // declaration and
38 {
39  return x>=std::sqrt(2.0)? -x : 2.0*x ; // definition of function t(x)
40 }
41 
42 // The three versions of Bisect differ by its signature
43 // declaration of Bisect
44 double Bisect(double a, double b, double eps);
45 // declaration of Bisect2
46 double Bisect(double a, double b);
47 // declaration of Bisect3
48 double Bisect(const std::function<double(double)> &func,
49  double a, double b, double eps);
50 
51 int main()
52 {
53  constexpr double EPS = 1e-6; // accuracy constant
54  array<string, 5> ssf{"f(x) := sin(x) - x/2",
55  "g(x) := (1.234567-x)*(x+0.987654)",
56  "h(x) := 3.0 - exp(x)",
57  "t(x) := 1-x*x",
58  "d(x) := x>=std::sqrt(2.0)? -x : 2.0*x" };
59 
60 // now with array of functions
61  array< std::function<double(double)>, 5> vff{f, g, h, t, dc};
62 
63  // map char to index
64  map<char, int> mmf{{'f', 0}, {'g', 1}, {'h', 2}, {'t', 3}, {'d',4}};
65 
66  // map char to function
67  map<char, std::function<double(double)> > mapff{{'f', f}, {'g', g}, {'h', h}, {'t', t}, {'d',dc} };
68 
69 
70  cout << endl;
71  cout << " Determine root in [a,b] by bisection " << endl;
72 
73  for (size_t k = 0; k < ssf.size(); ++k) {
74  cout << ssf[k] << endl;
75  }
76 
77  char choice;
78  cout << endl << "Which function do you prefer ? ";
79  cin >> choice;
80 
81  std::function<double(double)> ff;
82  try {
83  // http://www.cplusplus.com/reference/map/map/at/
84  ff = mapff.at(choice); //function variable
85  }
86  catch (out_of_range ) {
87  choice = 'h';
88  ff = mapff.at(choice);
89  cout << " incorrect choice. h(x) is used." << endl;
90  }
91 
92 
93  double a;
94  double b;
95  cout << " " << choice << "(a) > 0, a : ";
96  cin >> a;
97  cout << " " << choice << "(b) < 0, b : ";
98  cin >> b;
99  cout << endl;
100 
101  double const fa = ff(a);
102  double const fb = ff(b);
103  double x0;
104 
105  if (fa*fb<=0) { // one root in [a,b]
106  if ( abs(fa) < EPS || abs(fb) < EPS) { // solution is a or/and b
107  if ( abs(fa) < EPS ) { // solution is a
108  x0 = a;
109  cout << endl << " point of zero = " << x0 << endl;
110  }
111  if ( abs(fb) < EPS ) { // solution is b
112  x0 = b;
113  cout << endl << " point of zero = " << x0 << endl;
114  }
115  }
116  else { // root in open interval (a,b)
117  if ( fa < 0.0 ) { // f(a) < 0 && f(b) > 0
118  cout << "I have to swap a and b" << endl;
119  x0 = Bisect(ff, b, a, EPS); // Bisect(3) is called
120  }
121  else { // f(a) > 0 && f(b) < 0
122  x0 = Bisect(ff, a, b, EPS); // Bisect(3) is called
123  }
124  cout << endl << " point of zero = " << x0 << endl;
125  }
126  }
127  else { // no solution in [a,b]
128  cout << endl << "There is potentially no solution in [" << a << "," << b << "]" << endl;
129  }
130  cout << endl;
131 
132  return 0;
133 }
134 
135 // ---------------------------------------------------------------
136 // Recursive function Bisect3
137 // ---------------------------------------------------------------
138 // definition of Bisect3
139 
140 double Bisect(const std::function<double(double)> &func,
141  const double a, const double b, const double eps)
142 {
143  double const c = (a + b) / 2;
144  double const fc = func(c);
145  double x0;
146 
147  cout << a << " " << b << endl;
148  //if ( std::abs(fc) < eps ) {
149  if ( std::abs(fc) < eps || std::abs(b-a) < 1e-14) { // Modification for non-continuous functions
150  x0 = c; // end of recursion
151  }
152  else if ( fc > 0.0 ) {
153  x0 = Bisect(func, c, b, eps); // search in right intervall
154  }
155  else { // i.e., fc < 0.0
156  x0 = Bisect(func, a, c, eps); // search in left intervall
157  }
158 
159  return x0; // return with solution
160 }
161 
162 
163 
164 
165 
166 
167 
168 
169 
const double EPS
Definition: Bisect2.cpp:13
double Bisect(double a, double b, double eps)
Definition: Bisect6.cpp:124
double f(const double x)
Definition: Bisect7_dc.cpp:17
double dc(const double x)
Definition: Bisect7_dc.cpp:37
double g(const double x)
Definition: Bisect7_dc.cpp:22
double t(const double x)
Definition: Bisect7_dc.cpp:32
double h(const double x)
Definition: Bisect7_dc.cpp:27
int main()
Definition: Bisect7_dc.cpp:51
b
Definition: bisect.m:12
define interval a
Definition: bisect.m:11