9/2=4.5 is read as Expression 4 = 4.5 and fails check?

v4.5.1.stable.official [f62fdbde1] Linux

——————————————————————————–

Someone found a bug in one of our Godot 4 games and we don’t know how to fix:

In "“NumbersFall 110%”, when having below equation:

9/2=4.5

it is read as below:

4 = 4.5

and fails the check?

Code is below, any ideas how to fix the above?

func CheckEquationNewPerfect():
ConvertTilesToString()

print(ValueToCheck)

var splitEquation = ValueToCheck.split("=", true, 0)

var expression = Expression.new()
expression.parse(splitEquation[0])
var resultLeft = expression.execute()

var expressionTwo = Expression.new()
expressionTwo.parse(splitEquation[1])
var resultRight = expressionTwo.execute()

print(resultLeft, " / ", resultRight)

if (resultLeft == null or resultRight == null):  return(false)

if (is_equal_approx(resultLeft, resultRight) == true)

There are no bugs, at least not on expression evaluation side. 9/2 is indeed 4. It’s integer division. If you want floating point division, at least one of the operands must be of floating point type.

Do a regex replace that finds all numerical literals that don’t have a decimal point and appends it at the end, so 9/2 would become 9./2. and evaluate as you expect it to.

Alternatively, a somewhat simpler regex to construct would the one that adds float(*) around every numerical literal, regardless of it having a decimal point or not.

1 Like

Hi,

Thanks for the reply!
How would I do the above?

”VallueToCheck” is a string containing: “9/2=4.5”
”resultLeft“ is the everything left of “=”
”resultRight” is everything right of “=”

Thanks in advance…

NOTE # 1:
Function below is to convert selected tiles to String:

func ConvertTilesToString():
ThereIsAnOperator = false
ThereIsAnEqual = false

PlusIndex = -1
MinusIndex = -1
MinusTwoIndex = -1
MultiplyIndex = -1
DivideIndex = -1
DecimalIndex = -1
DecimalTwoIndex = -1
EqualIndex = -1

TheEnd = 0

CurrentClearedTiles = 0

ValueToCheck = ""
var index = 0
while (index < 18 and SelectedTilePlayfieldX[index] != -1 and  SelectedTilePlayfieldY[index] != -1):
	var selX = SelectedTilePlayfieldX[index]
	var selY = SelectedTilePlayfieldY[index]
	if (Playfield[selX][selY] > -1 and Playfield[selX][selY] < 16):
		CurrentClearedTiles+=1
		var part = Playfield[selX][selY]
		if   (part ==  0):  ValueToCheck+="0"
		elif (part ==  1):  ValueToCheck+="1"
		elif (part ==  2):  ValueToCheck+="2"
		elif (part ==  3):  ValueToCheck+="3"
		elif (part ==  4):  ValueToCheck+="4"
		elif (part ==  5):  ValueToCheck+="5"
		elif (part ==  6):  ValueToCheck+="6"
		elif (part ==  7):  ValueToCheck+="7"
		elif (part ==  8):  ValueToCheck+="8"
		elif (part ==  9):  ValueToCheck+="9"
		elif (part == 10):
			ValueToCheck+="+"
			PlusIndex = index
			ThereIsAnOperator = true
		elif (part == 11):
			ValueToCheck+="-"

			if (MinusIndex == -1):
				MinusIndex = index
			elif (MinusTwoIndex == -1):
				MinusTwoIndex = index

			ThereIsAnOperator = true
		elif (part == 12):
			ValueToCheck+="*"
			ThereIsAnOperator = true
			MultiplyIndex = index
		elif (part == 13):
			ValueToCheck+="/"
			ThereIsAnOperator = true
			DivideIndex = index
		elif (part == 14):
			ValueToCheck+="."

			if (DecimalIndex == -1):
				DecimalIndex = index
			elif (DecimalTwoIndex == -1):
				DecimalTwoIndex = index

		elif (part == 15):
			ValueToCheck+="="
			ThereIsAnEqual = true
			EqualIndex = index

		index+=1

pass

I don’t really understand your code but one way to transform the 9/2=4.5 expression could be to split the left side at the / character. Lets call the two numbers (9 and 2) a and b.

Now recombine them: var s := "float(%s)/%s" % [a, b]

This turns into float(9)/2, which executed is 4.5 as a float.

1 Like

Hi,

Game is MIT open-source on GitHub below:
https://github.com/savantsavior/numbersfall/blob/main/project_numbersfall/LogicCore.gd#L356

Just want a quick fix, this is pulling us away from another game project…

Exactly as I described. Are you familiar with regular expressions? If not, you should learn the basics. It’s an immensely powerful tool for any kind of string processing. Every programmer should know how to use them.

1 Like

Here’s an example:

var text = "9/2=4.5"
var re: RegEx = RegEx.create_from_string("[\\d\\.]+")
var text_floatized = re.sub(text, "float($0)", true)
print(text, " -> ", text_floatized)
var ex: Expression = Expression.new()
for token in text_floatized.split("="):
	ex.parse(token)
	print(ex.execute())

Output:

9/2=4.5 -> float(9)/float(2)=float(4.5)
4.5
4.5

Hi,

That will work, but have an issue making it work within our code:

I gave you an example to demonstrate the principle. It’s not meant to be directly pasted into your code. You need to understand what has been demonstrated and apply/adapt it to your specific use case.

token is a loop iterator, so of course it’s not defined outside of loop body scope.

Ok, it is working now, thank you…

func CheckEquationNewPerfect():
ConvertTilesToString()

var text = ValueToCheck
var re: RegEx = RegEx.create_from_string("[\\d\\.]+")
var text_floatized = re.sub(text, "float($0)", true)
var ex: Expression = Expression.new()
var exTwo: Expression = Expression.new()
var resultLeft = null
var resultRight = null
var token = text_floatized.split("=")
ex.parse(token[0])
exTwo.parse(token[1])
resultLeft = ex.execute()
resultRight = exTwo.execute()

if (resultLeft == null or resultRight == null):  return(false)

if (is_equal_approx(resultLeft, resultRight) == true):
	var numberOfOperators = 0
	var scoreAdd = 0

I just want to say that in general it’s a bit impolite to mark your own post as the solution when other people replied to you and helped you get there.

3 Likes

This happens a lot. But I think it’s because it’s not clear what and how mark as solution is used, not that people trying to get credit from other people’s help. Maybe the forum needs to make it more clear.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.