Variants of creating calculator. Can i calculate something in Label?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Konrad

Are there any variants how to create a calculator? In addition, can i calculate something in Label, like 2 + 5 and etc? Help me please. Сould you give me an example of a simple calculator.
Thankful in advance

:bust_in_silhouette: Reply From: jgodfrey

I’d guess you’re after the Expression class. WIth that, you can parse and execute a string-based expression.

See the details (and an example) here:

I read your guide, but i don’t understand how i can calculate something in Label.
I created calculator, but that script is very difficult to improving.
number1 = null, number2 = null , operation = " " onready var display = $Label
If number1 == null:
number1 = float(display.get_text())
display.set_text(" ")
number2 = float(display.get_text())
operation “+”

I also have an operation function, which doing operations.
I have a buttons like 1 ,2 ,3 and etc

Konrad | 2020-12-13 17:59

The point is, the Expression class can parse and execute a String as an expression. It doesn’t matter where the string comes from. It could be from a network connection, some text entered by a user into a LineEdit control, or (in your case), the text found in a Label (though, that sounds less useful) - it doesn’t matter.

Do you want to put the result (the answer) of the expression in the label, or will the label itself contain the expression?

To be clear, for this expression and result:

2 + 2 = 4

Is your label supposed to contain the 2 + 2 part or the 4 part? Displaying the result (the 4) makes the most sense, but if that’s the case, where does the expression (2 + 2) come from?

jgodfrey | 2020-12-13 18:08

Check my comment, i change it. Sorry for my english and thank you

Konrad | 2020-12-13 18:11

I’d suggest that you divide the problem into 2 parts. The first part would be to create a function that can accept a string that represents an expression and returns the result of that expression.

That’s (more or less) what the example in the documentation does.

Once you have that working, the second part would be to create a UI that will allow the expression string to be created. That would include the normal buttons found on a calculator (0-9, +, -, /, *, …) as well as some control to “see” the expression being constructed (probably a Label). As each button is pressed, they’d just add their character to the running expression.

When the expression string is complete, it’d be passed to the function created in step #1 above to be evaluated.

With both pieces, it becomes pretty simple. Just let the user construct the expression by pressing the available buttons (just like a real calculator). Then, pass the expression to your function for evaluation, and show either the result or the error (if the expression wasn’t valid for some reason).

jgodfrey | 2020-12-13 18:28

For the first piece (the expression parser), here’s a working version I just made. Give it a string representing an expression (such as 2 + 2 or (5 + 2) * 2 and it will return the result. If you give it an invalid expression, it will return an error message instead.

So, create a calculator-like UI to build the expression string, and you should have the parts you need.

func evaluate_expression(expression):
	var exp_obj =
	var result

	var error = exp_obj.parse(expression, [])
	if error != OK:
		result = exp_obj.get_error_text()
		result = exp_obj.execute([], null, true)
		if exp_obj.has_execute_failed():
			result = "Eval Error!"

	return str(result)

jgodfrey | 2020-12-13 18:45

There’s a full documentation page on using the Expression class in the latest branch of the documentation: Evaluating expressions — Godot Engine (latest) documentation in English

Calinou | 2020-12-13 21:27

Thank you, i made this. But how i can use “sqrt” or “function square”? In document was wrote only about simple operations like “*, /” and etc. May be create a number1 and number2? Or other variant?

Konrad | 2020-12-15 19:00

The doc page linked by Calinou above has an explicit example with the sqrt function. Really, it’s as simple as constructing an expression that includes it. The doc’d example is this expressiion:

sqrt(pow(3,2) + pow(4,2))

jgodfrey | 2020-12-15 19:29

So, i made sqrt. I dont know how change pow(x,y) to x^y. Because other people dont know that pow = ^. How i can replace pow to ^ ? I made 2 displays. In first display i put expression, second display doing caclulation and showing result. Thanks for help

Konrad | 2020-12-20 16:06

In addition to the built-in functionality, you can write your own functions that can be called during the expression parsing (as outlined in the docs mentioned above).

However, you really won’t be able to get something like x^y to be processed as a function call due to its structure / format.

My first thought would be to allow your User to add something like that to the expression string they build using your UI. Then, before passing the finished expression to the Expression class for processing, you could preprocess it as necessary.

So, you’d scan the finished expression string for that construct and replace it with a valid call to pow.

So, if you find 34^3 in the User’s expression, you’d replace it with pow(34,3) before passing it to Expression.

If you had a general preprocessing step in your process, you could perform other, similar substitutions as necessary based on your needs…

jgodfrey | 2020-12-20 16:36

i have no idease how i can do this. May be there is a document with guide or something else? I saw example with “double”, but its dont help me.
With sqrt i made this script:

func _on_sqrtbutton_pressed():
	hidenline.set_text(line.get_text() + " sqrt(")
	display.set_text(display.get_text() + "√(")

display - its label show expression and result.
hidenline - this line user dont see. It is doing calculation and etc. But all showing only “display”

Konrad | 2020-12-20 17:11

Yeah, that’s similar to my suggestion. The main difference is that I’m suggesting you let the user construct an expression string that looks like whatever you want. For instance using whatever mathematical symbols and syntax you want to support (sqrt, power, …).

Then, when the user finishes constructing the expression (on a traditional calculator, that’d be when the = button is pressed), you pass the user-defined expression to a preprocessor function that substitutes your allowed syntax with the syntax required by Godot’s Expression class.

So, for example, you might allow a user to enter this expression:

5 + 17^3 * √5

Since the expression class can’t parse that, you’d need to preprocess it to look like:

5 + pow(17,3) * sqrt(5)

To do that, you’d have to search the User-defined expression string and replace the parts where you’ve allowed special syntax with the syntax the Expression class requires.

With that done, you’d then pass the update expression to Expression for processing.

So, to recap:

  • Let the User enter the expression, including any special syntax you want to support
  • When the user is finished (presses the = button?)…
    • Pass the expression to your preprocessor function
    • Update the syntax as necessary for the Expression class
    • Get the result
    • Present the result to the User

jgodfrey | 2020-12-20 18:45

I know that I need to replace pow with ^ but I do not understand how exactly to do it. May be use “for” “in”, or there are other variant?

Konrad | 2020-12-20 19:06

I’d probably use the Regular Expression class as the basis for the mentioned preprocessing function. That provides very powerful pattern matching and replacement capabilities. That said, regular expressions can get quite complex.

Short of that, you could also just step through the expression string a character at a time to manually identify and replace the interesting substrings.

Neither way will be trivial. I’d definitely go the Regular Expression route.

Otherwise, the easiest way to do this would be to simply require the user to enter a syntax that’s already accepted by Godot’s Expression class. In that case, there’d be no preprocessing necessary.

jgodfrey | 2020-12-20 19:31