Implicit type conversion in GDScript - When math gets in the way

2min read
Game Dev Godot Engine

November 8, 2018

Formula thumbnail

While coding a simple AI for my (italian) Godot video tutorial series, I needed vectors with these kind of random values:

  • Vector2(0, 1)
  • Vector2(-1, 1)

Essentially I wanted to generate random values of 1, 0 or -1 and then use them as Vector2 coordinates.

There are multiple (simple) ways of doing this, but the first that came to my mind was a slightly convoluted mathematical approach:

I'm lazy and I prefer using pen and paper instead of MathJax, yes.

that translated into GDScript code is somethink like:

pow(-1, randi() % 2) * randi() % 2

Even if mathematically correct, this expression does not work as expected. When executing it, Godot complains about a bad float argument for the modulo operator %.

Error screen

The problem is that pow() returns a float number and I was not taking this into account (more on this later);

Types highlighted

this means that pow(-1, randi() % 2) * randi() is a multiplication of a float and an integer.
In this case GDScript will implicitly convert the integer to float and thus the result of the multiplication will be a float value, and here it is the problem: this float value will be used as operand for the modulo operator and this is not a valid operation.

I did not see this error at first because I was thinking in mathematical terms and (-1)^n, for n positive natural number, is always an integer number.

Fixing the expression

# fixed
pow(-1, randi() % 2) * (randi() % 2)

# old 
pow(-1, randi() % 2) * randi() % 2

Just use the parenthesis to give precedence to the ending randi() % 2 and the problem is solved.

It’s not a super interesting read, but I think that it’s always good to remember that the math that we use in code development is really different from the math that we use in other contexts.

comments powered by Disqus