I am currently working on an aerodynamics projects and I encountered some weird issues that involve numerical instability. At first, I was not sure if that was the case. I checked to see what happens when you enter a big number inside a Vector3. After entering numbers that were bigger than 16777217, numerical instability became an issue. So I consequently came up with a test to find out where this kind of strange behaviour starts. This is the script that I wrote to conduct the test:
local i = 0.0
local increment = 100
local n = 1
while true do
local vector = Vector3.new(i, 0, 0)
if vector.x ~= i then
local _error = vector.x - i
if math.abs(_error) > math.abs(n) then
print(i, _error)
n = n + 1
if n - 1 == 10 then
break
end
end
end
i = i + increment
end
The idea is to increment the variable i until the targeted axis of the Vector3 is unequal to i. The resulting number to cause numerical instability was â16777217â with an error of â1â.
Some more results I got are:
67108900 -4 - Server - Script:12
67109100 4 - Server - Script:12
67109300 -4 - Server - Script:12
134217800 -8 - Server - Script:12
134218200 8 - Server - Script:12
134218600 -8 - Server - Script:12
134219000 8 - Server - Script:12
268435500 -12 - Server - Script:12
268435600 -16 - Server - Script:12
268435700 12 - Server - Script:12
There are 2 reasons on why I wrote this article:
There is no warning for numerical instability on the documentation whatsoever
This is because of how floats work. 2^24 (16777216) is the largest consecutive number* that can be represented precisely as a float. This should probably still be documented, though.
That is true, but is there nothing that could be done to extend the domain of the value of a Vector3 axis? For example, in other programming and scripting languages, the float domain can be extended using the âlongâ type. I assume that it is not possible, since Vector3 is a Lua object and has Lua limitations.
Itâs a limitation of all Vector3s as they all use single-precision floating-points as their numbers.
The only way to get around it is to do the math on ânormalâ numbers which are in double-precision floating-point format and to convert them into Vector3s afterwards at the loss of precision when doing so.
Generally speaking you shouldnât need that much precision to begin with though.
Well, I am working on a project where one script calculates drag and lift. The problem is that at some rare occasions (for instance if a vehicle made of low-density material hits the water with great speed), I do actually hit those big numbers. I agree that almost no one ever has to deal with numerical instability, but I in fact do.
I do run calculations at a vector level so that might indeed result in some very unstable situations.
If you really need that much precision you will have to recreate the Vector3-class to run calculations with at the cost of having to reimplement the functions within it and it being a lot slower than native vector3 math.
As others pointed out, this is not a bug or unexpected behavior. Itâs merely a limitation of floating point precision.
While modern PCs could probably handle 64-bit floats, the issue comes down to lower-end devices needing to use 32-bit floats to run decently. Maintaining two different precision levels would be impractical and not worth the effort, so they just use 32-bit precision instead.
Again, these are floating-point errors, but instead, it is large numbers, just like the smaller ones. I have made a topic addressing about small errors in building which turned out to be floating-point errors.
It is also noticeable if you flung your character at really high speed away from the point of origin.