This site is version 0.0.1. Most of the code on this site is drafted by an agent and needs review. I apologize for the AI-speak, we are working on rewriting it!
viv-lang.org

← Posts

demoAINumerics

Three floating-point failures in summation, cancellation and RANDU

Adding for up to a million left to right ends 414 units in the last place (ulps) from the correctly rounded sum; Kahan's compensated sum is correctly rounded at all 31 checkpoints from 1 to . Evaluating from its expanded coefficients near gives rounding noise: 89 sign changes among 401 points, where the polynomial has one, and 8.5 times the true value at . The factored form is within everywhere. The random number generator RANDU puts every triple of successive draws on one of 15 planes.

Look inside this program

  • Atlas

    The program’s map: every function and which calls which.

  • There’s no recorded run of this program yet.

Each section computes something in double precision and compares it with an exact answer. The references are in posts/refs/kahan-summation-horner-noise-and-randus-planes.py (output beside it): Python's math.fsum, which returns the correctly rounded sum of its arguments and which the reference checks against exact rational arithmetic (fractions) up to ; the exact value of in rationals; and integer arithmetic for the generators.

A double has a 53-bit significand, so a sum, product or quotient of two doubles is the exact result times with . is the gap between 1 and the next double, and one ulp (unit in the last place) of a number is the gap between and the next double above it in magnitude, about .

Printed

SIG_BITS: 53
U_ROUND: 1.11022e-16

Tests 1 of 1 pass

  • a double has a 53-bit significand: 1 + 2^-52 is a double, 1 + 2^-53 rounds to 1, and the unit roundoff is 2^-53 (passes)

Summing

Adding term by term, each addition rounds the running sum, and the rounding errors pile up. Once the sum is near 14, a term like keeps only the bits that line up with the sum's last bit, about 30 of its 53. Kahan's method (1965) keeps a second variable holding what the last addition rounded away, and subtracts it from the next term before adding:

In exact arithmetic would be 0. In floating point, is the part of that made it into , and subtracting leaves the part that did not, with its sign flipped. The error of the result is at most about , independent of the number of terms, as long as is small.

The cell sums (each term the double nearest ) up to both ways and records both sums at 31 checkpoints spaced evenly in .

Printed

NAIVE_ULPS: [0, 0, 0, -1, -1, 0, 1, 0, 0, -2, 0, 3, 0, -2, 2, -2, -2, -2, -15, -18, -19, 4, 7, -4, 4, -52, -23, 80, -52, -23, -414]
KAHAN_ULPS: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
LAST_TERM: 1e-06
BITS_KEPT: 30
Sum of 1/k, k = 1 .. N: error in ulps of the exact sum
left to rightKahan
−400−200010⁰10¹10²10³10⁴10⁵10⁶Ncomputed - correctly rounded (ulps)

Tests 3 of 3 pass

  • the last term, 10^-6, meets a sum near 14 and keeps 30 of its 53 bits (passes)
  • Kahan's sum equals the correctly rounded sum at all 31 checkpoints (passes)
  • the naive sum is off at N = 10^4 by 19 ulps, at 10^5 by 52 and at 10^6 by 414 (passes)

near its root

Expanded, . Horner's rule evaluates it with seven multiplications and seven additions, . Near the partial results are 1, , 15, , 15, , 1, while the answer is tiny ( at ). Each partial result is rounded, by up to half an ulp of a number near 20, about , and those errors are as large as the answer. The rounding bound for Horner's rule (Higham, Accuracy and Stability of Numerical Algorithms, section 5.1) is with and the unit roundoff ; here it is about , and the measured errors reach of it.

The factored form has no such problem. For between and 2, is computed exactly (Sterbenz's lemma: the difference of two doubles within a factor of 2 of each other is a double), and then six multiplications each add a relative error of at most .

At , away from the root, Horner's value has a relative error of . Near the root it has no correct digits.

Printed

sign_changes: 89
worst: 5.48989e-15
worst_ratio: 0.0263797
6.66134e-16
7.8125e-17
$(x - 1)^7$: factored, and expanded by Horner's rule
0.98 to 1.02
Horner, expanded(x−1)7, factored
-1e-1201e-120.980.991.001.011.02xp(x)
0.995 to 1.005
Horner, expanded(x−1)7, factored
-5e-1505e-150.9960.9981.0001.0021.004xp(x)

Tests 6 of 6 pass

  • Horner's values change sign 89 times among the 401 points; the polynomial changes sign once (passes)
  • at x = 1.005 Horner gives 6.66e-16, 8.5 times the exact 7.8125e-17; the factored form is within 1.4 eps (passes)
  • the largest Horner error is 5.49e-15 (against exact rationals in the reference), 2.6% of Higham's bound (passes)
  • at x = 1.01 the answer is 10^-14, and a partial result near 20 is rounded by up to half an ulp, 1.78e-15 (passes)
  • for x from 1/2 to 2, x - 1 is exact: its rounding error, found by TwoSum, is 0 at 401 points (passes)
  • at x = 1.2 Horner's relative error is 5.8e-11 (passes)

RANDU's planes

RANDU was IBM's random number generator in the 1960s: , with draws . Its multiplier is , and squaring it gives . The first term vanishes modulo , and , so , and every three consecutive values satisfy

So is always a whole number. With each in that number lies between and 9, which puts every point on one of the 15 parallel planes . A simulation that uses triples of draws as points in a cube samples 15 planes instead of the cube.

The products here are below , so double-precision arithmetic computes them, and the remainders, exactly. The cell also runs MINSTD, the Park-Miller generator , for which the same combination is never a whole number in 3000 triples.

Printed

65539
26542323
1622650073
whole_randu: 3000
whole_minstd: 0
PLANES: [25, 89, 115, 204, 248, 321, 321, 348, 337, 297, 257, 204, 130, 81, 23]
max_product: 140735306463723
$9u_k - 6u_{k+1} + u_{k+2}$ against $u_k$, 600 triples
RANDU-5051000.20.40.60.81uk9uk−6uk+1+uk+2
RANDU
MINSTD-5051000.20.40.60.81uk9uk−6uk+1+uk+2
MINSTD

Tests 5 of 5 pass

  • every product 65539 x_k and 16807 x_k is below 2^48, so doubles hold it exactly (passes)
  • the first draws match the reference's integer arithmetic (passes)
  • 9 u_k - 6 u_(k+1) + u_(k+2) is a whole number for all 3000 RANDU triples, on 15 planes (passes)
  • the counts on the planes j = -5 and j = 9 are 25 and 23, as in the reference (passes)
  • for MINSTD the combination is a whole number in none of the 3000 triples (passes)

Checked when the site was built: 15 of 15 tests passed, in 1.3 s. Download 2026-09-25-kahan-summation-horner-noise-and-randus-planes.viv