'Test accuracy of math.hypot()' from math import hypot, frexp, ldexp from random import expovariate, triangular, gauss, shuffle from decimal import Decimal, getcontext from collections import Counter from pprint import pprint from sys import version_info getcontext().prec = 200 hist = Counter() def ulp(x): mant, exp = frexp(x) return ldexp(0.5, exp - 52) n = 1_000_000 reverse = True for k in (2, 3, 5, 10, 100, 1_000, 10_000): if k > 2 and version_info[:2] <= (3, 8): # 3.7 and prior only support the two argument form continue for i in range(n): args = [gauss(1_000_000_000, 300_000_000) for i in range(min(3, k))] args += [expovariate(1.0) for i in range(len(args) - k)] shuffle(args) expected = float(sum(x**2 for x in map(Decimal, args)).sqrt()) actual = hypot(*args) ulps = (actual - expected) / ulp(expected) hist[ulps] += 1 #print(expected.hex(), actual.hex(), ulps) print(f'k={k:,d}, n={n:,d}, reverse={reverse!r}') pprint(sorted(hist.items()), width=30)