Hi Joel

I really like your line of thought in the EWD function. I wish to draw your
attention to a problem with the numeric functions you chose to illustrate
the function. The problems are due to a flaw in the mathematical comparison
functions (< > <> = <= >=) in REBOL when they are applied to the decimal!
type. For instance:

-------snip------------
> EXAMPLES ========
>
> First, to address Ladislav's original example:
>
>     signum: func [n [number!]] [
>         ewd/if [
>             n < 0 [-1]
>             n = 0 [ 0]
>             n > 0 [ 1]
>         ]
>     ]
>
> with test cases
>
>     >> signum -12
>     == -1
>     >> signum 12
>     == 1
>     >> signum 2 - 2
>     == 0

The signum function does not actually return the sign of the argument for
all decimals.

>> signum -1e-16
== 0
>> signum 1e-16
== 0

---------snip------------

> A tidy-looking solution to a not-very-large problem: find the median
> (middle) of three argument values.
>
>     medianof3: func [a b c] [
>         ewd/do [
>             a > b [set [a b] reduce [b a]]
>             b > c [set [b c] reduce [c b]]
>         ]
>         b
>     ]
>

The medianof3 function does not actually return the median for all triples
of decimal values.

 >> medianof3 10e17 2e17 5e17
== 5E+17
>> medianof3 10e-17 2e-17 5e-17
== 2E-17

Some additional simple examples illustrating the problem:

>> 1e-16 = 1e-32
== true

>> 1e-16 > 1e-32
== false

>> positive? 1e-16 - 1e-32
== true

>> 1e-16 - 1e-32
== 1E-16

>> 0 = (1e-16 - 1e-32)
== true

>> zero? 1e-16 - 1e-32
== false

This is a rather unfortunate state of affairs for those using decimal
numbers in REBOL programs. I have investigated this problem fairly
extensively. The actual behavior of these comparison functions is rather
complex and is also dependent on things like whether one of the values is a
power of two or not, etc. The problem is not restricted to certain numbers;
the comparison functions can give inaccurate results over the entire range
of decimal values. A manifestation of the same problem had been noted in
mid-October by Eric Long. His compare.r script at rebol.org was written to
repair the built-in comparison operators. I do not know whether this problem
afflicts all platforms or is unique to the Windows version. Perhaps others
on the list can fill us in on that?

I have reported this to REBOL Tech as a bug. I also sent a fair amount of
supporting examples and a test program in REBOL to help them find the
problem. It has incident number 2.2.0.212. I have the impression that fixing
this bug may not be very high on their priority list. I had not planned to
post it to the general mailing list. However, when I see some code showing
someone has fallen into this trap, I feel that I should at least issue a
warning. Hence, this post.

There is a quick fix. The functions POSITIVE?, NEGATIVE?, and ZERO? give the
correct answers in all cases. So they can be used to test the difference of
two values. The prefix comparison functions could be temporarily replaced
with something like:

eq?: func [x y] [zero? x - y]
gt?: func [x y] [positive? x - y]
lt?: func [x y] [negative? x - y]

with >= being  not lt?  and <= being not gt?

These will work just fine and give the correct results as other languages
do. But we lose the use of infix notation. Until this bug is fixed, it is
best to avoid the built-in comparison operators altogether when working with
doubles. This is what I have done in my own code.

Sorry to go on for so long about a side issue to your neat function.
Let's hope this gets fixed real soon.

Cheers

Larry


Reply via email to