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

Vector floating point values are not matching what was assigned to it. #17971

Closed
K9Kraken opened this issue Apr 4, 2018 · 11 comments
Closed

Comments

@K9Kraken
Copy link

K9Kraken commented Apr 4, 2018

Godot version:

Godot 3.0.2

OS/device including version:

Manjaro Linux 17.1.7

Issue description:

When creating a Vector or assigning numbers to it that have floating point values results in the vector holding a number that is not equal to the original number.

The number in the vector should be the same number that was assigned to it. This has been causing me a few issues and road blocks in my development.

It is possibly the cause or related to these issues:
#17820
#17307

Also when trying to compare a number with floating point values to a vector's value it will return false even if they are the same exact number.

Steps to reproduce:

var x = 100.01
var v = Vector3(x, 0, 0)
print( x == v.x)
print(x)
print(v.x)

** Output **

False
100.01
100.010002
var v = Vector2(0, 0, 0)
v.x = 100.05
print(v.x)

** Output **

100.050003
var x = 1.01
var v = Vector2(x , 0)
print(v.x)
print(v.x == x)
print(v.x == 1.01)
v.x = 1.0
print(v.x == 1.0)

** Output **

1.01
False
False
True

******* I tested this in Godot 2.1.4 and the issue is similar *******
In Godot 2.1.4 a float suffers from this bug where in Godot 3.0.2 the float works correctly but the Vectors are still suffering from this bug.


var x = 100.01
var v = Vector3(x, 0, 0)
print(x)
print(v.x)
print(v.x == x)
print(v.x == 100.01)

** Output **

100.010002
100.010002
True
True
@K9Kraken K9Kraken changed the title Vector floating point values are not matching what is assigned to it. Vector floating point values are not matching what was assigned to it. Apr 4, 2018
@Chaosus
Copy link
Member

Chaosus commented Apr 4, 2018

its because float numbers does no support precise direct comparsion by nature, you should use something like this

func isEqual(v1, v2)
{
    return abs(v1 - v2) < 0.000001
}

@K9Kraken
Copy link
Author

K9Kraken commented Apr 4, 2018

Thanks I did not realize this. Perhaps GDScript should do this automatically.
However, the primary issue is with Vectors not holding the exact values that are assigned to them, this is causing issues such as seams in 3d tiles and possibly many other issues like the bugs with SurfaceTool.

@Chaosus
Copy link
Member

Chaosus commented Apr 4, 2018

However, the primary issue is with Vectors not holding the exact values that are assigned to them

Floating point (in fractional part) have "exact" values for human eyes, on program level they always contains inaccuracy(its their nature) and due its inaccuracy they cannot be correctly compared on equality(just it). But dont panic, this inaccuracy is invisible for human eyes, did you see seams in Minecraft ?
PS. I think about introducing core function which compare two floating point values with user-defined precision(simular to what I showed above).

@bruvzg
Copy link
Member

bruvzg commented Apr 4, 2018

@K9Kraken Numbers like 1/10 and 1/100 become recurring (infinite) fractions in binary, similar to 1/3 in decimal. You won't be able to store exact value of such number in any binary fixed or floating point format (even in arbitrary-precision one), only as separate numerator/denominator.

@K9Kraken
Copy link
Author

K9Kraken commented Apr 4, 2018

Thanks for the response, I was getting confused because I thought "vector.x = float" was the same as "float = float". Previous software I've used stored values in their vectors as floats so the numbers stayed the same when you assigned them.

Also thinking about this I don't think it is related to the issues I linked to above.

@mhilbrunner
Copy link
Member

Leaving this open as it's not yet clear if there is an bug here (in addition to the expected precision issues of float).

From IRC:

no, there is obviously some loss of precision due to a float/double conversion
while it isn't good to compare doubles for equality, it shouldn't behave worse than C due to a bug :)

@bruvzg
Copy link
Member

bruvzg commented Apr 4, 2018

Vector3 use single precision floats, Variant (default variable type) uses double precision, both can't represent 100.01, you only get same value out because print have limited output precision.

Single is 100.01000213623046875
Double is 100.0100000000000051159076974727213382720947265625

@bruvzg
Copy link
Member

bruvzg commented Apr 4, 2018

print only outputs up to 12 decimal digits, see ustring.cpp#L948-L949.

@aaronfranke
Copy link
Member

aaronfranke commented Aug 10, 2018

Unfortunately there is no way to have perfectly-precise representations of all decimal numbers in binary floating point formats. However, the solution as @Chaosus mentioned is to use approximate-equality comparison methods.

I have a pull request open here #18992 which does several things to improve approximate equality methods, including changing the Vector, Color, etc, comparison methods to use approximate equality comparisons, and exposing these to GDScript. print(x == v.x) will still fail, but comparing two vectors will work, and print(is_equal_approx(x, v.x)) will also work.

@aaronfranke
Copy link
Member

#18992 added ways to properly check for equality, and the other half of this issue is a duplicate of #288, as vectors will match assigned values when they use doubles.

@akien-mga
Copy link
Member

Closing as per above comment.

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

Successfully merging a pull request may close this issue.

6 participants