Numerical instability of Vector3

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
7 Likes

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.

7 Likes

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.

1 Like

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.

3 Likes

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.

1 Like

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.

4 Likes

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.

7 Likes

I was not aware of this at first. This is one of the reasons why I do not like untyped languages.

1 Like

If you’re not aware, Roblox Lua is a statically typed language—you just have to opt in by adding --!strict at the start of your script.

For more information, read this page.

1 Like

I forgot about that. Maybe I will use it in the future.

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.

1 Like

Nice, that is quite interesting.