Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

Why are there discrepancies in the position of my elevator?

I have the following code:

f1.ClickDetector.MouseClick:connect(function()
if base.Position.Y > 0 then
	repeat	
	base.CFrame = base.CFrame - Vector3.new(0, .1, 0)
	f1.CFrame = f1.CFrame - Vector3.new(0, .1, 0)
	f2.CFrame = f2.CFrame - Vector3.new(0, .1, 0)
	f3.CFrame = f3.CFrame - Vector3.new(0, .1, 0)
	f4.CFrame = f4.CFrame - Vector3.new(0, .1, 0)
	wait(.1)
	until base.Position.Y <= 0
else end
end)

f2.ClickDetector.MouseClick:connect(function()
	if base.Position.Y > 10 then
	repeat	
	base.CFrame = base.CFrame - Vector3.new(0, .1, 0)
	f1.CFrame = f1.CFrame - Vector3.new(0, .1, 0)
	f2.CFrame = f2.CFrame - Vector3.new(0, .1, 0)
	f3.CFrame = f3.CFrame - Vector3.new(0, .1, 0)
	f4.CFrame = f4.CFrame - Vector3.new(0, .1, 0)
	wait()
	until base.Position.Y <= 10
	elseif base.Position.Y < 10 then
	repeat
	base.CFrame = base.CFrame + Vector3.new(0, .1, 0)
	f1.CFrame = f1.CFrame + Vector3.new(0, .1, 0)
	f2.CFrame = f2.CFrame + Vector3.new(0, .1, 0)
	f3.CFrame = f3.CFrame + Vector3.new(0, .1, 0)
	f4.CFrame = f4.CFrame + Vector3.new(0, .1, 0)
	print(base.Position.Y)
	wait()
	until base.Position.Y >= 10
	else end
end)

However, neither performs the operation I want with accuracy. Instead of simply .1, the code adds something like .100000000001789. Why is this? Can someone explain to me why this is happening, and a possible solution? Thanks.

1 answer

✓ Accepted answer

CFrames and Vector3s are internally stored as "floats" -- 32-bit floating-point numbers.

This means you have about ~24 bits, which is about around 8 significant digits. 0.1 isn't exactly representable in binary (only numbers with powers of 2 as denominator are), so you get some error when you try to use 0.1 -- you'll get something like 0.10000000?????.... Using it more and more will cause a larger and larger error.

That said, you shouldn't have to be concerned about this error normally. Further, you can't update parts to a higher precision -- internally, Vector3s and CFrames have this amount of precision.


If you're having troubles because this imprecision means you go far over the limits, e.g., to 9.9 or 10.1, you can fix this by treating the problem differently.

Instead of

while y < target do
	local move = 0.1
	y = y + move
	wait()
end

Use something like:

while y < target do
	-- THE LESSER OF how far I need to, and the maximum speed:
	local move = math.min( 0.1, target - y )
	y = y + move
	wait()
end

This also has the advantage of letting you use time deltas.

The amount of time that wait() actually pauses for can wildly vary. It's usually best (at least with small wait times) to actually use the time that has elapsed:

moveRate = 3 -- studs/second
while y < target do
	-- THE LESSER OF how far I need to, and the maximum speed:
	local move = math.min( 0.1, target - y )
	y = y + moveRate * wait()
end

This discussion is preserved as it was. New answers, comments, and votes are closed.