Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

Innacuracies with math.sqrt() and ^2 solution?

Asked by 8 years ago
Edited 8 years ago

I was trying to determine if 3 points created a right triangle and was using the Pythagorean Theorem when I ran into a massive headache of a problem, which I'll get to in a little bit. The first thing I did was calculate the sidelengths using the following code

A,B,C=Vector3(10,0,0).new,Vector3.new(10,10,0),Vector3.new(0,10,0) --These are just example Vector3's for my problem
local CA=math.sqrt((A.X-C.X)^2+(A.Y-C.Y)^2+(A.Z-C.Z)^2)
local CB=math.sqrt((B.X-C.X)^2+(B.Y-C.Y)^2+(B.Z-C.Z)^2)
local BA=math.sqrt((A.X-B.X)^2+(A.Y-B.Y)^2+(A.Z-B.Z)^2)

Now for some strange reason

print(CB^2+BA^2, CA^2)
print(CB^2+BA^2==CA^2)

prints out

200,200
false

The only explanation I can think of is something with roblox rounding the numbers when displayed but behind the scenes these two numbers are ever so slightly askew due to innacuracies with math.sqrt() or ^2. Is there any way to get around this without losing significant accuracy?

0
Using (num+.01/2)-((num+.000001/2)%.01) to round each number fixes the problem but this feels like an inefficient method, if it's all that can be done then I guess it'll suffice however I would really prefer not to have to do something like that, GeorgeLopezScripter 25 — 8y
0
Answered your comment User#6546 35 — 8y

2 answers

Log in to vote
1
Answered by 8 years ago

Magnitude

Honeygold is most likely correct, and this is a floating-point comparison issue, but I would like to point out that you can skip doing this sort of length comparison with excessive math (Slow) by simply using

A,B,C=Vector3(10,0,0).new,Vector3.new(10,10,0),Vector3.new(0,10,0) --These are just example Vector3's for my problem
local CA=(A-C).magnitude
local CB=(B-C).magnitude
local BA=(A-B).magnitude

After that you can just compare closeness of them.

print(CB^2+BA^2, CA^2)
print(math.abs((CB^2+BA^2)-CA^2) < 0.001) -- Closer than 0.001 difference to eachother? They're probably realistically the same.
0
Is .magnitude really any faster than just doing the math myself? I'm sure that using .magnitude just does almost exactly what I did myself but not visibly, the most variation I can imagine is avoiding x^2 with x*x GeorgeLopezScripter 25 — 8y
0
You have to remember that computing the magnitude C++ sided is going to probably be faster than doing it Lua sided, although I could be wrong as Roblox is really notorious for throwing logic out the window. Regardless, doing it from Lua technically gives you a more precise result (although not really important). The real question is, do you believe it's more readable to do the Pythagorean theorem jakedies 315 — 8y
0
... to do the pythagorean theorem explicitly or to just use the Magnitude property of V3s? jakedies 315 — 8y
0
Computing the magnitude C-side is going to be faster than computing it Lua-side, especially given the extra hidden metamethod invocations you're making by accessing X/Y/Z in each Vector3 User#6546 35 — 8y
Ad
Log in to vote
0
Answered by 8 years ago
Edited 8 years ago

I am almost certain that this is a floating-point error, which (long story short) prevents exact representation of numbers with decimals.

print(0.2 + 0.1 == 0.3) -- This prints false.
print((0.2 + 0.1) - 0.3 == 0) -- This prints false.
print((0.2 + 0.1) - 0.3 < 0.0000001) -- This prints true.

The fastest solution when checking for equality with decimals is to check if (the absolute value of) the difference is less than some small number.

Answer this question