codeplea / tinyexpr

tiny recursive descent expression parser, compiler, and evaluation engine for math expressions
https://codeplea.com/tinyexpr
zlib License
1.61k stars 245 forks source link

When evaluate simple expression with only one variable, nan is returned over 150 #85

Closed Sercurio closed 3 years ago

Sercurio commented 3 years ago

I've tried to evaluate the expression "t" and print the result side by side with the t variable.

double t=0;
te_expr *expr;
int err;

void loop(){
  te_variable vars[] = {"t", &t};
  te_expr *expr = te_compile("t", vars, 1, &err);

  Serial.print(te_eval(expr));
  Serial.print("  |  ");
  Serial.print(t);
  Serial.println();
  t++;
}

t is on the right and evaluate t is on the left 144.00 | 144.00 145.00 | 145.00 146.00 | 146.00 147.00 | 147.00 148.00 | 148.00 149.00 | 149.00 nan | 150.00 nan | 151.00 nan | 152.00

We can saw that over 150 returned result is t.

What is the problem?

codeplea commented 3 years ago

Can you post a minimal but complete example?

Sercurio commented 3 years ago

For information, I'm using this library because it's work with arduino. https://github.com/tetrahalomethane/tinyexpr

#include "tinyexpr.h"

te_expr *expr;
int t=0;
int err;

void setup() 
{
    Serial.begin(9600);
}

void loop() 
{
    te_variable vars[] = {"t", &t};
    te_expr *expr = te_compile("t", vars, 1, &err);

    Serial.print(te_eval(expr));
    Serial.print("  |  ");
    Serial.print(t);
    Serial.println();

    delay(100);
    t++;
}
codeplea commented 3 years ago

Earlier you posted double t, now you say it's int t? Which is it?

Here's how your program would look as standard C code:

(Note that t should be a double, and you're missing a pair of {} for vars.)

#include "tinyexpr.h"
#include <stdio.h>

te_expr *expr;
double t=0;
int err;

int main() {
    te_variable vars[] = {{"t", &t}};
    te_expr *expr = te_compile("t", vars, 1, &err);

    while (1) {
        printf("%f", te_eval(expr));
        printf("  |  ");
        printf("%f", t);
        printf("\n");
        t++;
    }
}

And it works perfectly that way.

I'm guessing that your problem is related to Arduino, or some porting issues. You might want to post this over at https://github.com/tetrahalomethane/tinyexpr I have no idea what changes were made to get this to work as Arduino code.

Sercurio commented 3 years ago

The maintener of the forked repo doesn't seems very active. So I tried another thing. I import the stlport library (https://github.com/vancegroup/stlport-avr/tree/STLport-master-arduino-installed) And use the tinyexpr library of ur repo. I needed to comment out the fabs function in order to compile.

But i get the same result and over 150, the t_eval expression return nan.

the other weird thing is if I reassign the t variable at 0 after reaching 149, the evaluation doesn't work too.

Can be a memory problem with dynamic allocation? Cause if I evaluate a single time the expression with t=150 it works.

codeplea commented 3 years ago

Ok, I'm pretty sure you are running out of memory. Every time you are calling te_compile() it's allocating memory, and you're not calling te_free() so it runs out of memory after a while. You're also not checking the return value or err, so... yeah.

You can just put a call to te_free() at the bottom of your loop, but what would work even better is to only call te_compile() one time, like this:

#include "tinyexpr.h"

te_expr *expr=0;
double t=0;
int err;

void setup() 
{
    Serial.begin(9600);
}

void loop() 
{
    if (!expr) {
        /* Only call te_compile on the first loop. */
        te_variable vars[] = {{"t", &t}};
        expr = te_compile("t", vars, 1, &err);
        if (!expr) {
            Serial.print("te_compile error ");
            Serial.print(err);
        }
    }

    Serial.print(te_eval(expr));
    Serial.print("  |  ");
    Serial.print(t);
    Serial.println();

    delay(100);
    t++;
}

Calling te_compile only once will also save a lot of processing power too.

Sercurio commented 3 years ago

Ok, I feel so dumb right now... I forgot to call te_free()...

Thanks mate and ur wonderful library !