I plan to do the following:
void setup(){
String term = "12 + (2 * 5)";
int result = eval(term); // eval function (from Python)
Serial.println(result); // expecting 22
}
However there is no eval function. Are there any alternatives?
I plan to do the following:
void setup(){
String term = "12 + (2 * 5)";
int result = eval(term); // eval function (from Python)
Serial.println(result); // expecting 22
}
However there is no eval function. Are there any alternatives?
TinyExpr does what you want, and more.
TinyExpr is a very small recursive descent parser and evaluation engine for math expressions. It's handy when you want to add the ability to evaluation math expressions at runtime without adding a bunch of cruft to you project.
In addition to the standard math operators and precedence, TinyExpr also supports the standard C math functions and runtime binding of variables.
You'd just need to save tinyexpr.h
and tinyexpr.c
next to your Sketch.
#include "tinyexpr.h"
void setup() {
Serial.begin(115200);
}
void loop() {
char term[] = "12 + (2 * 5)";
Serial.println(term);
int error;
double result = te_interp(term, &error);
if (error){
Serial.println("Problem with expression.");
} else {
Serial.printf(" = %.10g\n", result);
}
delay(1000);
}
It outputs:
12 + (2 * 5)
= 22
Since term
is known at compile-time, this example is not very useful, and it simply outputs 22
in an endless loop.
If you use the input from Serial
, you can write a very basic interactive console. A String
has been used for conciseness, but this example could be rewritten with cstrings:
#include "tinyexpr.h"
void setup() {
Serial.begin(115200);
}
void loop() {
if (Serial.available() > 0) {
String expression = Serial.readStringUntil('\n');
Serial.print("> ");
Serial.println(expression);
int error;
double result = te_interp(expression.c_str(), &error);
if (error) {
Serial.print(" ");
for (int i = 0; i < error; i++) {
Serial.print(" ");
}
Serial.println("↑");
Serial.println("I didn't understand this part.");
} else {
Serial.printf(" = %.10g\n", result);
}
}
delay(50);
}
TinyExpr knows the order of operations, and it understands many other mathematical expressions:
> 12 + 2 * 5
= 22
> 3^5
= 243
> exp(7)
= 1096.633158
> (1 + sqrt(5)) / 2
= 1.618033989
> 1 + 2 * 3 + 4 * 5
= 27
> sin(pi/2)
= 1
> sin(pi/3)
= 0.8660254038
If there's a syntax error somewhere, error
tells you the position of the first encountered error:
> 3 +
↑
I didn't understand this part.
> sin() * 5
↑
I didn't understand this part.
> 3 / (4 + 5 * 7
↑
I didn't understand this part.
No, there are no alternatives. You need to parse the string and perform the operations yourself.
Personally I prefer to use RPN since it is so much easier to parse. Your string could be re-written then as:
2,5,*,12,+
Tokenise on ,
and look to see if it's a number (push on a stack) or an operator (pop operands off stack, do operation, push result on stack).
I Googled and the news isn't good. There isn't an off the shelf function that does this in C/C++. There are plenty of links to algorithms that you could implement. But would you have the memory to do it on an Arduino?
So, looking at the problem for a different perspective why don't you run python on the Arduino? There is a version called pymite which runs on a mega.