Skip to content

var_to_str rounds floats, losing massive precision in the process #78204

@mgc8

Description

@mgc8

Godot version

4.0.3.stable.official.5222a99f5

System information

MacOS Ventura 13.4, M1 Max

Issue description

When converting a float variable to string for serialisation using var_to_str, the expectation would be that the resulting string is simply the exact same variable as a string, e.g. 1.15 becoming "1.15".

This happens correctly for small values, but even as soon as the value goes above four digits, the result is rounded up/down. For over six digits, even the integer part is reduced to zero:

print(var_to_str(12345.54321)) => 12345.5
print(var_to_str(123456789.54321)) => 1.23457e+08 => which is 123457000 (!)

A certain amount of precision loss would be expected with floating point numbers, but not at these small values and so egregiously.

This is particularly problematic when trying to serialise time values as unix timestamps, which are by default all floats; it can be worked around by casting everything to "int" first, but that looses the sub-second precision.

Steps to reproduce

This exemplifies the problem by comparing integer and float serialisation/de-serialisation for the same values:

	var x_int = {
		"start": int(Time.get_unix_time_from_system()),
		"end": int(Time.get_unix_time_from_system()) + 15,
		"message": "test int",
	}
	var x_float = {
		"start": Time.get_unix_time_from_system(),
		"end": Time.get_unix_time_from_system() + 15,
		"message": "test float",
	}

	print("Int before:")
	print(x_int)
	var x_int_converted := var_to_str(x_int)
	print("Int converted:")
	print(x_int_converted)
	x_int = str_to_var(x_int_converted)
	print("Int after:")
	print(x_int)

	print("\n")
	print("Float before:")
	print(x_float)
	var x_float_converted := var_to_str(x_float)
	print("Float converted:")
	print(x_float_converted)
	x_float = str_to_var(x_float_converted)
	print("float after:")
	print(x_float)

Result:

--- Debugging process started ---
Godot Engine v4.0.3.stable.official.5222a99f5 - https://godotengine.org
OpenGL API 4.1 Metal - 83.1 - Compatibility - Using Device: Apple - Apple M1 Max
 
Int before:
{ "start": 1686693113, "end": 1686693128, "message": "test int" }
Int converted:
{
"end": 1686693128,
"message": "test int",
"start": 1686693113
}
Int after:
{ "end": 1686693128, "message": "test int", "start": 1686693113 }


Float before:
{ "start": 1686693113.04444, "end": 1686693128.04444, "message": "test float" }
Float converted:
{
"end": 1.68669e+09,
"message": "test float",
"start": 1.68669e+09
}
float after:
{ "end": 1686690000, "message": "test float", "start": 1686690000 }
--- Debugging process stopped ---

Minimal reproduction project

test-var-to-str.zip

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions