Processing math: 100%
11.001001000011111101101010100010001000 Arithmazium
Home

find_ulp_of_one_minus() – the iteration

The code continues im parallel with the case for ulps just larger than 1.0, but with a twist. To investigate values immediately less than 1.0, we look at the expression 1(1ϵ) where ϵ is a tiny value, not necessarily a whole number of ulps of numbers less than one.

The wrinkle is that we must take care not to lose a digit off the right hand side by consuming a digit in the one's place.

The idiom for computing 1w when w<1is to use two operations 1/2+(1/2w) avoiding use of the one's palce in any subexpression. The formula above expands to 1/2+(1/2(1/2+(1/2ϵ))) which you will see in four lines of the code below.

In the loop, y is half a whole number of ulps plus a small nudge. When subtracted from ONE_HALF the result rounds to 1/2δ, where Greek delta is a whole number of ulps of values just less than 1.0.

The combined expression ONE_HALF + (ONE_HALF - y) is exactly 1δ. We then apply the same tecchnique to compute 1(1δ) to isolate δ, iterating until it is down to a single ulp.

This binary diagram starts with 3 ulps of values just less than 1.0. It illustrates the computation of 1δ

ONE    100 ... 00 1.0, showing binary point alignment u = ...    000 ... 011 suppose u is 3 ulps of 1.0- y = ONE_HALF * u + ...    000 ... 00110... y is half u, with nonzero low bits y = ONE_HALF - y    001 ... 1?? does not yet round back to 1/2 x = ONE_HALF + y    011 ... 1?? a value just less than 1

Next, we subtract from 1.0in two steps to isolate the difference.

y = ONE_HALF - x   -001 ... 1?? strips the leading bit and flips sign x = ONE_HALF + y    000 ... 0?? magnitude subtract, leaving just low bits

As in the parallel case, the loop terminates when the halved value falls off to zero when rounded or when u is pinned.

    while True:
        u = x
        y = ONE_HALF * u + THIRTY_TWO * u * u
        y = ONE_HALF - y
        x = ONE_HALF + y
        y = ONE_HALF - x
        x = ONE_HALF + y
        if u <= x or x <= ZERO: break
    return u


Your turn

Exercise: Complete the binary case started in the diagram above, assuming rounded arithmetic, to see that it results in one ulp of 1.0.

Exercise: The decimal diagram below starts the iteration in 6-digit rounded decimal arithmetic.

ONE    100000 1.0, showing decimal point alignment u = ...    0000005 suppose u is 5 ulps of 1.0- y = ONE_HALF * u + ...    00000025 the trailing 5 is half an ulp of 1- y = ONE_HALF - y    0499998 value 0.4999975 rounded up x = ONE_HALF + y    0999998 1 less two ulps of 1- y = ONE_HALF - x   -0499998 exact x = ONE_HALF + y    0000002 down to two ulps of 1-

Continue the loop to find one ulp of 1.0.

Exercise: Complete the computation in 6-digit chopped octal arithmetic.

u = ...    000005 suppose u is 5 ulps of 1.0 in octal y = ONE_HALF * u + ...    0000024 the 4 is half an ulp of 1- y = ONE_HALF - y    03777754 the trailing 4 chops off x = ONE_HALF + y    0777775 exact y = ONE_HALF - x   -0377775 exact x = ONE_HALF + y    0000003 one more step toward an ulp of 1-
Home