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.