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.
Exercise: Verify the comparison in 6-digit decimal.
Exercise: Verify the comparison in binary.
Exercise: Carry out the subtraction in 6-digit octal.
Exercise: Carry out the subtraction
for 1.0 plus an ulp in decimal.
Exercise: Carry out the subtraction
for 1.0 plus an ulp in binary.