Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vector2 math bit corruption #50251

Closed
ghost opened this issue Jul 7, 2021 · 3 comments
Closed

Vector2 math bit corruption #50251

ghost opened this issue Jul 7, 2021 · 3 comments

Comments

@ghost
Copy link

ghost commented Jul 7, 2021

Godot version

3.3.2.stable.official

System information

Windows 10

Issue description

Doing maths with _Vector2_s returns slightly corrupted answers 👀, though the x and y components should be floats and not lose any precision, leading me to believe that this is not due to floating point errors.

This might be due to unnecessary maths going on in the background, perhaps deteriating the precision of the numbers.

The example in the steps to reproduce better illustrate the problem.

This bug might lead to rotated _Vector2_s having a value larger than their original length!

Steps to reproduce

func _ready() -> void:
	var anumber : float = -0.1234567
	var actual_answer : float = -123.4567
	print("multiply_then_extract_x " + var2bytes((Vector2(anumber, 0) * 1000).x).hex_encode())
	print("extract_x_then_multiply " + var2bytes(Vector2(anumber, 0).x * 1000).hex_encode())
	print("multiply_original_float " + var2bytes(anumber * 1000).hex_encode())
	print("actual_answer           " + var2bytes(actual_answer).hex_encode())

Minimal reproduction project

Run the above code in Godot.

@kleonc
Copy link
Member

kleonc commented Jul 7, 2021

The cause is the same as in #50022: Vector2.x, Vector2.y are float (32-bit) on the C++ side but in GDScript float is 64-bit so there are conversions happening all over in different places.
This C++ snippet shows what conversions lead to the results in your example:

#include <iostream>

void print_as_hex(float f) {
	std::cout << std::hex << *((uint32_t*)&f) << std::endl;
}
void print_as_hex(double d) {
	std::cout << std::hex << *((uint64_t*)&d) << std::endl;
}

int main() {
	double anumber = -0.1234567;
	double actual_answer = -123.4567;
	
	print_as_hex((float)((float)anumber * (double)1000));
	print_as_hex((double)(float)anumber * (double)1000);
	print_as_hex(anumber * (double)1000);
	print_as_hex(actual_answer);
	
	return 0;
}

Output:

c2f6e9d5
c05edd3a99800000
c05edd3a92a30553
c05edd3a92a30553

@Calinou
Copy link
Member

Calinou commented Jul 7, 2021

Is there a way to force _Vector2_s to use double precision?

Not yet, see #288.

@aaronfranke
Copy link
Member

@SlitheringMule I agree with you. Although I think having 32-bit floats as an option is still useful.

That said, this issue is a duplicate of godotengine/godot-proposals#892, closing. If you want to see this implemented, feel free to give the proposal a 👍 and let people know about this problem and the proposal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants