godot
godot copied to clipboard
String to float doesn't work as expected
Godot version: v3.2.3.stable.official
Issue description: After creating a number from a string that number doesn't equal itself
Steps to reproduce:
# 1. Multiple values comparison test
var tests = [
["1.3", 1.3],
["1.23", 1.23],
["1", 1]
]
for test in tests:
var num = float(test[0])
if num == test[1]:
print(str(test[0]) + " and " + str(test[1]) + " are equal") # only 1 will be equal
else:
print(str(test[0]) + " and " + str(test[1]) + " are not equal") # 1.23 and 1.3 will not be equal
# 2. Checking for a whole number
var string = "1.3" # 1.3
var number = float(string) * 10 # 13
if fmod(number, 1) == 0.0:
print("whole number")
else:
print("not whole number because the result is: ", fmod(number, 1)) # 1 instead of 0
# 3. Simple comparison test
var extra_string = "1.3" # 1.3
var extra_number = float(extra_string) * 10 # 13
if extra_number == 13:
print("expected")
else:
print("not expected")
I also tested the #3 test using php and I got the expected behavior.
My main use case is to find if the number is whole or not. I understand that I can compare float using a method like this
const FLOAT_EPSILON = 0.00001
static func compare_floats(a, b, epsilon = FLOAT_EPSILON):
return abs(a - b) <= epsilon
You can't accurately represent 1.3 and 1.23 as a FP numbers and thus 1.3 * 10 != 13. Use is_equal_approx to compare FP numbers (as you suggested yourself).
To demonstrate that precision is the issue:
extends MainLoop
func _init():
print(float("1.3") * 10 == 13.0)
print(float("1.25") * 10 == 12.5)
Output:
False
True
Godot 3.2.3.stable.official using PopOS 20.10.
I was going to open a new issue, but decided to do it here instead. There seems to be some sort of misbehaviour when converting floats to strings. Somehow it sometimes works as expected but sometimes it doesn't. Just in case, I'm not talking about comparing them, I'm talking about the value that gets displayed.
var cast_f : float = float('4.99')
var convert_f : float = str2var('4.99')
print(cast_f, ' - ', convert_f)
print(cast_f * 10, ' - should be 49.9')
print(convert_f * 10, ' - should be 49.9')
prints:
4.99 - 4.99 49.899998 - should be 49.9 49.9 - should be 49.9
I was going to open a new issue, but decided to do it here instead. There seems to be some sort of misbehaviour when converting floats to strings. Somehow it sometimes works as expected but sometimes it doesn't. Just in case, I'm not talking about comparing them, I'm talking about the value that gets displayed.
In Godot 4, this is no longer an issue. It seems like internally the accuracy of floats for the intents of the visualization has been upgraded to use 64 bits, matching the float Variant type.

Regarding this original proposal, those kind of situations may be less common as a result of this. Not sure it's worth writing "Use is_equal_approx"one more time in the otherwise unrelated conversion method. Maybe?