11.001001000011111101101010100010001000 Arithmazium
Home

Precision

We discovered the radix by looping in search of a carry into the B's place of a large power of \(2\).

Now, we discover the precision – the number of significant digits carried – by adding \(1\) to successive powers of B until the addition finally triggers rounding. The diagram looks the same in any radix. It's shown here in binary.

# in loop: big_b + 1.0    010 ... 01 large power of B to which 1 can be added # next big_b + 1.0    100 ... 01 largest power of B to which 1 can be added # final big_b + 1.0   1000 ... ?0 the added 1 rounds off on most machines, binary VAX with add-half-and-chop will round up

The rounding arises when B is raised to the power that is the precision of the number system. The code sidelines the case of radix 1.0, perhaps because of log arithmetic. Otherwise, we call find_precision_big_B_to_nth() to loop on powers of B until adding 1.0 causes no increase.

# Compute PRECISION and BIG_B_NTH = B**PRECISION barely too big
# to satisfy (BIG_B_NTH + 1) - BIG_B_NTH == 1 .
# Basic 1240-1270
if B == ONE:  # defer to the secondary calculation below
    PRECISION = ZERO
    BIG_B_NTH = big_2_nth
else:
    PRECISION, BIG_B_NTH = find_precision_big_B_to_nth(B)

The N in BIG_B_NTH is the precision, barring very anomalous rounding behavior. This means that \(B ^ {-(N-1)}\) should be an ulp of 1.0, and \(B ^ {-N}\) should be an ulp of numbers just less than 1.0.

BIG_B_NTH = ...   1000 ... 00 power of B such that added 1 rounds off ONE / BIG_B_NTH    000 ... 001 1/B of a unit in the last place of 1 (ONE / BIG_B_NTH) * B    000 ... 01 a unit in the last place of 1

We record these guesses for now and move on to further refinement.

guess_ulp_of_one_minus = ONE / BIG_B_NTH
guess_ulp_of_one_plus = B * guess_ulp_of_one_minus
print("Closest relative separation found is ULP_OF_ONE_MINUS = {:0.7e} ."
      .format(guess_ulp_of_one_minus))
Home