a more precise distance algorithm

Steven D'Aprano steve at pearwood.info
Mon May 25 23:11:14 EDT 2015


On Tue, 26 May 2015 05:21 am, ravas wrote:

> I read an interesting comment:
> """
> The coolest thing I've ever discovered about Pythagorean's Theorem is an
> alternate way to calculate it. If you write a program that uses the
> distance form c = sqrt(a^2 + b^2) you will suffer from the lose of half of
> your available precision because the square root operation is last. A more
> accurate calculation is c = a * sqrt(1 + b^2 / a^2). If a is less than b,
> you should swap them and of course handle the special case of a = 0. """


Let's compare three methods. 


import math
import random

def naive(a, b):
    return math.sqrt(a**2 + b**2)

def alternate(a, b):
    a, b = min(a, b), max(a, b)
    if a == 0:  return b
    if b == 0:  return a
    return a * math.sqrt(1 + b**2 / a**2)

counter = 0
print("Type Ctrl-C to exit")
while True:
    counter += 1
    a = random.uniform(0, 1000)
    b = random.uniform(0, 1000)
    d1 = naive(a, b) 
    d2 = alternate(a, b)
    d3 = math.hypot(a, b)
    if not (d1 == d2 == d3):
        print("mismatch after %d trials" % counter)
        print("naive:", d1)
        print("alternate:", d2)
        print("hypot:", d3)
        break



When I run that, I get:

mismatch after 3 trials
naive: 1075.6464259886257
alternate: 1075.6464259886257
hypot: 1075.6464259886254

A second run gives:

mismatch after 3 trials
naive: 767.3916150255787
alternate: 767.3916150255789
hypot: 767.3916150255787


which shows that:

(1) It's not hard to find mismatches;
(2) It's not obvious which of the three methods is more accurate.



-- 
Steven




More information about the Python-list mailing list