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