4

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?

1
  • Guess there is more to this question as "String term = 12 + (2 * 5);" can be evaluated at compile time. Dec 23, 2016 at 6:42

3 Answers 3

5

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.

Your example

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.

Basic interactive console

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.
1

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).

1
0

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.