Math Problems

Hello, I am in a problem that I do not know how to solve it, I need to make a calculator that can solve several mathematical problems in a single line, such as: ((4 * 5) + 3) / 5. First I tried to find a way in which I can use large numbers and decimals, so I used the BigNumbers.h library, it allows me to use giant numbers (I don't need such large numbers, but with this I solve the problem) and decimals. But there was another problem, Arduino doesnt have the function eval() as in JS that allows me to do these things (((4 * 5) + 3) / 5), and neither did I find an algorithm on the Internet to simulate the eval(). But I found a library (expression_parser.h, very heavy) that simulates the eval(), the problem with this is that it only shows 2 decimal places.

Possible solutions:

  1. Find a way that these two libraries can be merged. (very difficult)
  2. Find an algorithm to solve these mathematical problems (respecting the PEMDAS rule) with the BigNumbers.h library. (easy?)
  3. Use a library that allows me to use JS, this would help to use large numbers with decimals and use the function eval(). (easy, but it takes a lot of memory)
  4. Edit the library expression_parser.h to show more than 2 decimal places. (hard)

I think number two is the right answer, but I have no idea how to do the algorithm.

I would do all of this on an Esp8266 with the Arduino IDE (to avoid memory problems).

Thanks!!!

1 Like

I'm sorry. What was your Question ?

Ehh... I want to be able to solve math problems like ((3726621 * 2346.28313) * 4.38262) / 58263, taking into account that I must be able to handle large numbers with many decimals.

The usual question...:smiley:

What do you mean with is a usual question? Is it easy to fix it?

@angeloziel, if you want to drive a programmer nuts, then go to a forum where they are (this forum) and ask questions with words as "large numbers" and "many decimals" :o and then not telling which libraries you talk about and not using the words "text" or "string" :o :o

You can use "modify" to change the title of your top post. For example: "Solve any math expressions which is in a string".

When you mention the BigNumber library, you could give a link to it, so others who don't know it can take a look at it: GitHub - nickgammon/BigNumber: BigNumber library for the Arduino

First of all, have a look at this table at 19:40 #353 How to use STM32 boards with Arduino IDE and how fast are they? (incl. surprise) - YouTube.
The ESP32 is a lot better with double precision float numbers.

How large are "large numbers" ?
How many decimals is "many decimals" ?

Is the 64-bit double precision good enough for you ?

Doing math is no problem, either with the double precision float or BigNumber.
Do you want to calculate the math that is in a text string ? Then you would need an interpreter. I don't know such an interpreter. Can you give a link to "expression_parser.h" so I can have a look at it.

The Arduino Serial.println() only prints 2 decimals by default. Use the second parameter if you want more: Serial.println() - Arduino Reference

The term PEMDAS is not very well known outside the US.

Well, I knew doing this was hard, but I didn't know it was hard for everyone too. But hey, there is option 3, it will cost me some memory but it would solve this.
This is what I know ... there are many tutorials showing how to use JS on the Esp8266 but it all has to do with the web pages. I don't want to create a web page to use JS, I just want to have a part of all the code in JS to be able to solve these math problems.

I can do this if someone shows me a small example code, a code where they have a library that allows me to use the JS, move an Arduino data to the JS part (like moving an "int" or "String" and converting it into a JS variable), process this data in JS and return the result to Arduino. With this all my problems would be solved and I would not have to use the two libraries that I mentioned in the first message.

Hmm. This is not simple, particularly if you mean that you want to

  • take an expression as a string of characters
  • parse out the numbers and operators
  • hold the numbers as arbitrary-precision big integers
  • evaluate the expression respecting the bodmas/pedmas rules

I mean - let's say someone wants to evaluate 1/3. How many decimals will you want? Or do you want to hold all the values as exact fractions - using a bigger denominator when necessary? But do you want exponentation? If so, using fractions is not an option, because 2^(1/2) does not have an exact fractional representation. Best you could do, if you want exact numbers, is to reduce the expression to its simplest exact form? For the general case, AFAIK the result would be the sum of a number of terms each of the form a/b * c/d ^ (e/f), eg: 3 + 2 * 5^(7/13)

So, your first question is representation. What do you really, really want? (Shout out to the Spice Girls).

The other difficult problem is the pedmas. To do that, you need a proper parser - google "LALR(1) parser" for a taster of what's involved. The parser builds an in-memory tree of the structure of the expression, then the nodes of the tree are solved from the leaves to the root. Early calculators solved this problem by using reverse polish notation - google "reverse polish notation".

So, assuming that we are not trying to do exponentation you'd parse the expresssion. Each number would be converted to an exact fraction - decimal places handled by multiplying by 10 until you had integers. The parser would build a tree of operators, and then you'd implement +-*/ to work over the fractions and produce a fraction as a result. For the output, you'd either print out the fractional result, or do it as a decimal - working out where the reapeating section starts. 97/70 would be rendered 1.3[857142], or something like that.

If you want to do exponentation, then the values would be a list of those basic expressions - the sum of which is the value - and the +-/^ operations would have to be able to work with lists like that. eg, you 'd have to write something to express 35^(1/2) + 5*3^(1/5) exponentiated by 2^(1/3)-7^(15/13) as a sum of terms.

If you really want it exact.

It's do-able, but this is not a simple ask. You could certainly use a library if there is one, but the question of how to go about doing that really depends on the library.

Or, or, you could just use 64-bit floating-point numbers, which are more than accurate enough for most practical purposes.

Perhaps the take-away from this is that you young whipper-snappers don't really get just how much these convenient high-level interpreted languages do for you. One of the useful things about programming for the arduino is that it gives you a taste of what is going on under the hood, that being: a lot.

Can you describe what the original goal is ?
Where does the text with the math expression come from ? What will you do with the result ?
Sometimes someone tries to find a solution for the wrong problem. I hope you are not stuck in a XY-problem.

What you want to do requires processing power from a computer or phone that runs a operating system and can run code on top of that.

When a ESP8266 (or ESP32) has JavaScript, then the source code of the script is on the ESP8266 and the JavaScript engine inside the browser on the computer/phone runs it. The ESP8266 has no idea that it is JavaScript, because the browser only requests a text file from the ESP8266, that's all.
You can not run a JavaScript-engine on a ESP8266 as far as I know.

Also Python can do a "eval()". There is a microPython for the ESP8266, but I don't know if it has the "eval()" included. The microPython can be used instead of the Arduino sketch. They can not be used together as far as I know.

A Raspberry Pi is a complete computer. You can do everything that a linux computer can do.

An Arduino is perfectly capable of doing expression parsing, assuming there are reasonable limits on the complexity of the expression, and the operators to be allowed. Defining those things should be the starting point of the discussion.

Google "arduino calculator" for some examples of (I'll bet you guessed it already!), calculators using Arduino.

RayLivingston:
An Arduino is perfectly capable of doing expression parsing, assuming there are reasonable limits on the complexity of the expression, and the operators to be allowed. Defining those things should be the starting point of the discussion.

The question is, where does the expression come from? What is creating the expression? And, why is it creating the expression rather than just calculating the result?

Why does the JavaScript code contain eval? Is there a good reason for it to contain eval?

What is the real problem? Are you trying to create a calculator?

RayLivingston:
An Arduino is perfectly capable of doing expression parsing, assuming there are reasonable limits on the complexity of the expression, and the operators to be allowed. Defining those things should be the starting point of the discussion.

If the goal is simply to create a calculator, then RPN (Reverse Polish Notation) neatly dodges the need for expression parsing. It is also much easier and much, much quicker to input math using RPN than using parentheses. Just make sure you have room for a high-enough stack: I would recommend allowing a stack height of at least 6, although the makers of Hewlett-Packard calculators felt that 4 was sufficient.

Thanks for all the tips, I already realized what I'm really dealing with. And it's a challenge that I want to take, I'm going to take the RPN method and what it derives from it (using the BigNumbers.h library to handle all kinds of numbers).

These are the pages where I am investigating:

I still haven't finished converting all this information into code, but if you have any suggestions, tell me :stuck_out_tongue: ... Thanks for your help!

Sorry we could not help. It seems that you are swimming alone in the deep. Let us know if you have something working to test on a ESP8266. You could try StackExchange, but be clear that you have also asked it here and give a link to this thread.

https://www.codeproject.com/Articles/88435/Simple-Guide-to-Mathematical-Expression-Parsing

  1. Edit the library expression_parser.h to show more than 2 decimal places. (hard)

The default number of decimal places printed by the print() function is 2 when printing the float (or double) data type. The print() function accepts a second argument, when printing floats, to specify the number of decimals.

float pi = 3.14159;
Serial.print(pi, 4);

// prints 3.1415

Koepel:
Sorry we could not help. It seems that you are swimming alone in the deep. Let us know if you have something working to test on a ESP8266. You could try StackExchange, but be clear that you have also asked it here and give a link to this thread.

But they did help me. They gave me information that I didnt know, information that helped me find exactly the formula to convert a whole line of mathematical problems in a string to a result, with the RPN method. I think this could not be done on an Arduino Uno since it doesnt have much RAM, but Im doing this project on an Esp8266, so there will be no problem.

groundFungus:
The default number of decimal places printed by the print() function is 2 when printing the float (or double) data type. The print() function accepts a second argument, when printing floats, to specify the number of decimals.

float pi = 3.14159;

Serial.print(pi, 4);

// prints 3.1415

Yes, I tried that too, and I was surprised to receive a result, but unfortunately I realized that there are errors when asking for more than two decimal places. It does not show me the decimals correctly, and it is not because of an error in the library, but because that is how the "float" works in Arduino, I would have to create a library to correctly calculate the decimals. But that's what BigNumbers.h is for.

angeloziel:
Thanks for all the tips, I already realized what I'm really dealing with. And it's a challenge that I want to take, I'm going to take the RPN method and what it derives from it (using the BigNumbers.h library to handle all kinds of numbers).

These are the pages where I am investigating:
Shunting yard algorithm - Wikipedia
Operator associativity - Wikipedia
Notación polaca inversa - Wikipedia, la enciclopedia libre

This is a general programming question and not specific to Arduino. Try searching for information on "recursive descent math equation parser", or something similar. There is plenty of example code on github. Reverse polish, polish and infix are separate notations and require different techniques for parsing. For example, RPN can be easily parsed using a simple stack.