![]() |
Attention | Topic was automatically imported from the old Question2Answer platform. |
![]() |
Asked By | af7567 |
I know that floating point number precision can be a bit off, but I am confused why a float from a Vector3 would be any different from a standard float. I was trying to work out why my 1 became a 0, and my 12 became 11 when converted from float to int and after a bit of playing around I found that the problem was caused by Vector3.
The following code demonstrates the problem:
func _ready():
# Wrong result:
var test_point = Vector3(3.8, 3, 7.5)
var i = test_point.x / 3.8
print("i as float: ", i)
var int_i = int(i)
print("i as int: ", int_i)
# Right result:
var j: float
j = 3.8
j = j / 3.8
print("j as float: ", j)
var int_j = int(j)
print("j as int: ", int_j)
I get the following output:
i as float: 1
i as int: 0
j as float: 1
j as int: 1
I am using Godot 3.3.2.stable on Linux 64-bit
Super strange behavior. I think this belongs as a github issue. Mathematically Vector3(x,y,z) / n = Vector3(x/n, y/n, z/y) therefore Vector3.x / n = x / n
so unless otherwise noted in the docs the order in which you perform operations shouldn’t matter.
In your case doing int(Vector3.x / float) == 0
while doing int((Vector3 / float).x) == 1
.
As a work around you can do var i = (test_point / 3.8).x
to get the results you desire.
timothybrentwood | 2021-08-19 02:54
This is not bug.
You’re getting such results of “unspecified behavior” because of combination of optimization, float precision specifics, and unspecified (by you) type-conversion operation.
Just change line #04 to either of
var i = test_point.x / test_point.x
var i = round(test_point.x / 3.8)
var i = ceil(test_point.x / 3.8)
And your “wrong” part will become “right” one.
sash-rc | 2021-08-19 10:27
“unspecified (by you) type-conversion operation.” That’s the problem. Do the same operations on both, and everywhere in the editor you can and see they’re both assigned to the value 1 (printing them, using the remote scene tree). Yet for some reason as an end user using int()
on one of the 1s and int()
on the other 1 results in two different behaviors.
var some_float = 3.8
var v = Vector2(some_float, some_float)
var f1 = float(v.x / some_float)
var f2 = float((v / some_float).x)
var f3 = float(some_float / some_float)
printt(f1, f2, f3)
printt(int(f1), int(f2), int(f3))
If you can explain to me as an end user, not going into the black box of the internals, why you would get 2 of the results from int()
the same and one different for the above code then I would love to hear it. I don’t think ‘floating point precision’ is a good enough answer when both f1
and f2
result in 1
when printing them and looking at the remote scene tree. I would agree if you could see the binary representation of them somewhere using the editor but to my knowledge you can’t.
timothybrentwood | 2021-08-19 12:25
you could see the binary representation of them somewhere using the editor but to my knowledge you can’t.
Of course you can, add print("%.20f " % f1, "%.20f " % f2, "%.20f" % f3)
and you’ll see:
0.99999998745165370000 1.00000000000000000000 1.00000000000000000000
You can use more decimals in format / print, like print("%.20f" % value)
:
The float
numbers are named like this because they are never (guaranteed to be always) precise, nor consistent across platforms like integers.
But what is more important, you should explicitly control type conversions wherever it matters, like use ceil()
, round()
, stepify()
etc. instead of just int()
sash-rc | 2021-08-19 13:09