11.001001000011111101101010100010001000 Arithmazium
Home

Compare ulps of 1

We now test values just greater than and less than 1.0. The easy computations are laid out below for you to complete.

This sequnece exposes an asymmetry in Paranoia's constants. In the previous section, we computed ONE_MINUS_ULP, the value next less than 1.0. To get the value next greater, we write out ONE + ULP_ONE_PLUS, which is expected to be computed without rounding error in any floating point arithmetic that will survive this program. There's no need for a named constant.

milestone = 20  # ==============================
test_cond(err_failure, ONE_MINUS_ULP - ONE_HALF < ONE_HALF,
          "(1-ULP_OF_ONE_MINUS)-1/2 < 1/2 is FALSE, prog. fails?")

# BUG in C version. The point is to try two cases of x.
for x in [ONE_MINUS_ULP, ONE + ULP_OF_ONE_PLUS]:
    y = x - ONE_HALF
    z = y - ONE_HALF
    test_cond(err_failure, (x != ONE)
              or (z == ZERO), "Comparison is fuzzy,x=1 but x-1/2-1/2 != 0")

Another topic that runs a thread through Paranoia is how numerical comparison behaves versus subtraction. Is asking whether x is equal to y the same as asking whether x - y is zero? It turns out that, historically, both comparison and subtraction could have different surprising properties on different machines.

Your turn

Exercise: Verify the comparison in 6-digit decimal.

ONE_MINUS_ULP    0999999 next less than 1.0 in 6 digits ONE_HALF    0500000 exact if radix is even ULP_ONE_PLUS - ONE_HALF    0499999 the subtraction is exact

Exercise: Verify the comparison in binary.

ONE_MINUS_ULP    011 ... 111 next less than 1.0 ONE_HALF    010 ... 000 exact ULP_ONE_PLUS - ONE_HALF    001 ... 111 should compare < 1/2

Exercise: Carry out the subtraction in 6-digit octal.

x = ONE_MINUS_ULP    0777777 next less than 1.0 in 6-digit octal y = x - ONE_HALF    0377777 should be exact in any arithmetic z = y - ONE_HALF   -0000001 should be small negative value

Exercise: Carry out the subtraction for 1.0 plus an ulp in decimal.

x = ONE + ULP_ONE_PLUS    100001 next greater than 1.0 in 6 digits y = x - ONE_HALF    0500010 exact, with a digit to spare to the right of the trailing 1 z = y - ONE_HALF    0000010 should be exact and nonzero

Exercise: Carry out the subtraction for 1.0 plus an ulp in binary.

x = ONE + ULP_ONE_PLUS    100 ... 01 next greater than 1.0 y = x - ONE_HALF    010 ... 010 exact, with a bit to spare to the right of the trailing 1 bit z = y - ONE_HALF    000 ... 010 should be > zero
Home