User input String to Funktion f(x)

Hi,

i am new to C++ and this Forum. I am Student at the DH-University in Mannheim Germany and for exercise purpose i am writing a program which in the end will contain all the mathematic and statistic mathematic stuff i learn similar to a more advanced calculator.
Now i want to add a class which transforms an user input string like "f(x) = 5*x*x*x + sin(x)" to a usable form so the program can then sent the information to other classes for example a differentiation class.
Hope you understand my problem.
Can you give me any advise on how to do that, or a link (i am maybe not the 1st to ask this but couldnt find the answer yet)

Kind regards


 
   fpad y = 5*x*x*x + sin(x); // thats how i would like to sent the user input funktion to the class  
Last edited on
This is very very complicated for someone just starting. Commercial programs for this can cost hundreds of dollars. If you want a complex program like that, you should ask your math department if they have one that you can use. If you want to learn programming, start with something simpler.
http://en.wikipedia.org/wiki/Shunting-yard_algorithm

Following is a variation of classic Dijkstra 2 stack algorithm.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
#include <map>
#include <stack>
#include <functional>
#include <utility>
#include <stdlib.h>

using namespace std;

int main(int argc, char** argv) {
  stack<double> s;  stack< pair<int, char> > ops;

  auto p = [&s, &ops] (function<double (double, double)>& f)
    {double r=s.top();s.pop();r=f(s.top(),r);s.pop();s.push(r);ops.pop();};

  map< char, pair< int, function<double (double, double)> > > m =
    {{'+', {1, [](double a, double b){return a+b;}}},{'-', {1, [](double a, double b){return a-b;}}},
     {'*', {2, [](double a, double b){return a*b;}}},{'/', {2, [](double a, double b){return a/b;}}}};

  const int order = 2; int level = 0;
  for (char* sp = argv[1];; ++sp) {
    while (*sp == '(') {level += order; ++sp;}

    s.push(strtod(sp, &sp));

    while (*sp == ')') {level -= order; ++sp;}

    if (!*sp) {while(!ops.empty()) p(m[ops.top().second].second); break;}

    const int op =  m[*sp].first + level;
    while (!ops.empty() && ops.top().first >= op) p(m[ops.top().second].second);

    ops.push(make_pair(op, *sp));
  }

  cout << s.top() << endl;
  return 0;
}
Here is Dijkstra code: http://habrastorage.org/getpro/habr/comment_images/532/3b4/a47/5323b4a47b1039df5b46fb310f711720.png
Yay295: Well I know that this very first program I would like to write is not the easiest one but I also think that that’s just a good way to learn C++ in an efficient way for me. I calculated about 6-9 Month to get it done and I am not the person to give up on things just because the might get a little complicated ;) (Hope that’s not offending)

MiiNiPaa: Thanks for the code, I am currently trying to understand and test it but I just don’t figure out how to run it because it gives me an error. “m = { “ <- that braked doesn’t seem to be allowed (well that’s what my compiler says (Microsoft Visual C++ 2010))

Last night I was working on some forward propagating automatic differentiation class see below. Just in case I wasn´t quite clear about how its supposed to work/ what i need it for. (dont worry about Line 3 since thats not the problem right now and apologize the German)

Right now i can just run it with for exaple " fpad y = 5*x*x*x + sin(x); " (I use a string to give me all f(x) and f'(x) i want. Later some other class is sopposed to produce the equation but for now i want the user to insert an equation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408

#include <iostream> 
#include <cmath> 
//#include"exprtk.hpp" // error in exprtk because of gettimeofday in line 22000 sth.

//////////////////////

double cot(double z)
{
  return 1.0 / tan(z);
}

double sec(double z)
{
  return 1.0 / cos(z);
}

double csc(double z)
{
  return 1.0 / sin(z);
}
double arcsin(double z)
{
  return 1.0 / sin(z);
}

double arccos(double z)
{
  return 1.0 / cos(z);
}

double arctan(double z)
{
  return 1.0 / tan(z);
}
double arccot(double z)
{
  return 1.0 / (1 / tan(z));
}

double acot(double z)
{
 return 1.0 / (1 / tan(z));
}

double ln(double z)
{
 return log(z);
}

double coth(double z)
{
return cosh(z) / sinh(z);
}

double arsinh(double z)
{
  return log(z + sqrt(z*z+1));
}

double arcosh(double z)
{
 return log(z + sqrt(z*z-1));
}

double artanh(double z)
{
 return 1/tanh(z);
}

double arcoth(double z)
{
 return 1/(cosh(z) / sinh(z));
}
////////////////////////////

class fpad // forward propagating automatic differentiation 
{ 
private:
  double value_; 
  double deriv_; 
public: 
  fpad(double v, double d=0) : value_(v), deriv_(d) {} 
  
  double value() const {return value_;} 
  double derivative() const {return deriv_;} 
  
  const fpad& equalsTransform(double newVal, double outer_deriv)  // Kettenregel 
  { deriv_ = deriv_ * outer_deriv;
    value_ = newVal; 
	return *this;
  } 
  
  const fpad& operator+=(fpad const& x) 
  { value_ += x.value_; 
    deriv_ += x.deriv_; 
    return *this; 
  } 
  
  const fpad& operator-=(fpad const& x) 
  { value_ -= x.value_; 
    deriv_ -= x.deriv_; 
    return *this; 
  } 
  


  const fpad& operator*=(fpad const& x) // Produkt-Regel:
  {  
    deriv_ = deriv_ * x.value_ + value_ * x.deriv_; 
    value_ *= x.value_; 
    return *this; 
  }  



  const fpad& operator/=(fpad const& x) //Quotientenregel
  {
	deriv_ = (deriv_ * x.value_ - value_ * x.deriv_) / (x.value_ * x.value_) ; 
	value_ *= x.value_; 
	return *this;
  }


  friend const fpad operator/(fpad const& a, fpad const& b) 
  { fpad r(a); r/=b; return r; } 

  friend const fpad operator+(fpad const& a, fpad const& b) 
  { fpad r(a); r+=b; return r; } 
  
  friend const fpad operator-(fpad const& a, fpad const& b) 
  { fpad r(a); r-=b; return r; } 
  
  friend const fpad operator*(fpad const& a, fpad const& b) 
  { fpad r(a); r*=b; return r; } 
}; 
 
///// Trigometrische /////

fpad sin(fpad t) 
{ 
  using std::sin; 
  using std::cos; 

  double v = t.value(); 
  t.equalsTransform(sin(v),cos(v)); // Verkettung 
  return t; 
} 
 

fpad cos(fpad t) 
{ 
  using std::sin; 
  using std::cos; 

  double v = t.value(); 
  t.equalsTransform(cos(v),-sin(v)); // Verkettung 
  return t; 
} 


fpad tan(fpad t) 
{ 
  using std::cos; 
  using std::tan;

  double v = t.value(); 
  t.equalsTransform(tan(v),(1/(cos(v)*cos(v)))); // Verkettung 
  return t; 
} 


fpad cot(fpad t) 
{ 
  using std::sin; 

  double cot(double d);
  

  double v = t.value(); 
  t.equalsTransform(cot(v),(-1/(sin(v)*sin(v)))); // Verkettung 
  return t; 
} 


fpad sec(fpad t) 
{ 
  using std::cos; 

  double sec(double d);

  double v = t.value(); 
  t.equalsTransform(sec(v),(sin(v)/(cos(v)*cos(v)))); // Verkettung 
  return t; 
} 


fpad csc(fpad t) 
{ 
  using std::sin; 
  using std::cos; 

  double csc(double d);

  double v = t.value(); 
  t.equalsTransform(csc(v),(-1/sin(v))*(cos(v)/sin(v))); // Verkettung 
  return t; 
} 


fpad arcsin(fpad t) 
{ 
 
  double arcsin(double d);

  double v = t.value(); 
  t.equalsTransform(arcsin(v),(1/sqrt(1-v*v))); // Verkettung 
  return t; 
} 
  
fpad asin(fpad t) 
{ 
  using std::asin;

  double v = t.value(); 
  t.equalsTransform(asin(v),(1/sqrt(1-v*v))); // Verkettung 
  return t; 
} 


fpad arccos(fpad t) 
{ 
 double arccos(double d);

  double v = t.value(); 
  t.equalsTransform(arccos(v),(-1/sqrt(1-v*v))); // Verkettung 
  return t; 
} 


fpad acos(fpad t) 
{ 
  using std::acos;

  double v = t.value(); 
  t.equalsTransform(acos(v),(-1/sqrt(1-v*v))); // Verkettung 
  return t; 
} 

fpad arctan(fpad t) 
{ 
  double arctan(double d);

  double v = t.value(); 
  t.equalsTransform(arctan(v),(1/(1+v*v))); // Verkettung 
  return t; 
} 


fpad atan(fpad t) 
{ 
  using std::atan;

  double v = t.value(); 
  t.equalsTransform(atan(v),(1/(1+v*v))); // Verkettung 
  return t; 
} 


fpad arccot(fpad t) 
{  
  double arccot(double d);

  double v = t.value(); 
  t.equalsTransform(arccot(v),(-1/(1+v*v))); // Verkettung 
  return t; 
}


  fpad acot(fpad t) 
{  
  double acot(double d);

  double v = t.value(); 
  t.equalsTransform(acot(v),(-1/(1+v*v))); // Verkettung 
  return t; 
}



///// Exponentialfunktionen /////

fpad exp(fpad t) 
{  
  using std::exp;

  double v = t.value(); 
  t.equalsTransform(exp(v),exp(v)); // Verkettung 
  return t; 
}
// hier fehlt/missing: a^x -> (ln a) * a^x



///// Logarithmusfunktionen /////

fpad ln(fpad t) 
{  
  double ln(double d);

  double v = t.value(); 
  t.equalsTransform(ln(v),(1/((v)))); // Verkettung 
  return t; 
}

fpad log(fpad t) 
{  
  using std::log;

  double v = t.value(); 
  t.equalsTransform(log(v),(1/((v)))); // Verkettung 
  return t; 
}
// hier fehlt/missing: logax -> (1/(log a)*x)



///// Hyperbelfunktionen /////

fpad sinh(fpad t) 
{  
  using std::sinh;
  using std::cosh;

  double v = t.value(); 
  t.equalsTransform(sinh(v),cosh(v)); // Verkettung 
  return t; 
}

fpad cosh(fpad t) 
{  
  using std::sinh;
  using std::cosh;

  double v = t.value(); 
  t.equalsTransform(cosh(v),sinh(v)); // Verkettung 
  return t; 
}

fpad tanh(fpad t) 
{  
  using std::tanh;
  
  double v = t.value(); 
  t.equalsTransform(tanh(v),(1-tanh(v)*tanh(v))); // Verkettung 
  return t; 
}

fpad coth(fpad t) 
{  
  double coth(double d);

  double v = t.value(); 
  t.equalsTransform(coth(v),(1-coth(v)*coth(v))); // Verkettung 
  return t; 
}



///// Areafunktionen /////

fpad arsinh(fpad t) 
{  
  double arsinh(double d);
  
  double v = t.value(); 
  t.equalsTransform(arsinh(v),(1/sqrt((v)*(v)+1))); // Verkettung 
  return t; 
}

fpad arcosh(fpad t) 
{  
  double arcosh(double d);
  
  double v = t.value(); 
  t.equalsTransform(arcosh(v),(1/sqrt((v)*(v)-1))); // Verkettung 
  return t; 
}

fpad artanh(fpad t) 
{  
  double artanh(double d);
  
  double v = t.value(); 
  t.equalsTransform(artanh(v),(1/((v)*(v)-1))); // Verkettung 
  return t; 
}

fpad arcoth(fpad t) 
{  
  double arcoth(double d);
  
  double v = t.value(); 
  t.equalsTransform(arcoth(v),(1/((v)*(v)-1))); // Verkettung 
  return t; 
}

// feel free to copy the code for any use, if you have suggestions on how to improve it please write me a message 
Last edited on
I just don’t figure out how to run it because it gives me an error. “m = { “ <- that braked doesn’t seem to be allowed (well that’s what my compiler says (Microsoft Visual C++ 2010))
It uses C++11 features, so it would not work with VS2010. I suggest you to upgrade to the 2013 version.
You can see how is it work here:
coliru.stacked-crooked.com/a/18990b2b393fa813
(Note that I placed formula into string in the beginning of main)
Thanks a lot that will really help me.

I tried a lot today with the piece of code you gave me but still dont get it to work. I think I understand the concept but not how to connect it.

Thats the way I solve the equations right now for testing at least the class I posted earlier seems to work:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include"ableiten.h"
//#include"exprtk.hpp"
#include<string>
int ableiten() 
{ 

  std::string expression_string;
  int iXstart;
  int iXend;
  double iXstepp;

  std::cout << "Please insert your equation: f(x) = ";
  std::cin >> expression_string ; // user should insert the Equation I tried different stuff with string and char arrays but I think I dont understand the way it has to be connected
  std::cout << "Which intervall do you want to derive?" << std::endl << "from: x =";
  std::cin >>  iXstart;
  std::cout << std::endl <<"to:   x =";
  std::cin >>  iXend;
  std:: cout << "Steppsize of intervall: x2-x1 =";
  std::cin >> iXstepp;



  std::cout << expression_string << "\n"
               "f (x) = " << "f'(x) = " << "\n";

  double x;
  for (x = iXstart; x <= iXend; x += iXstepp)
  {

  fpad x (x, 1.0); // Identitaet für x=1
                       // 1.0 ist die Ableitung der Identitaet 
  fpad y = 5 * x*x*x + sin(x)/cos(x)+exp(x)*10/x*x; 

  std::cout << y.value() << "	|	" <<  y.derivative() << std::endl;
  }

  return 0;
}




Hope thats not a stupid question I still wait on my text book (the one from Bjarne Stroustrup) to ship in, so I just have the internet to get information from right now.
Last edited on
Topic archived. No new replies allowed.