# Re: Comparing rationals/floats

```On Fri, Apr 15, 2005 at 04:18:51PM -0700, gcomnz wrote:
: More questions stemming from cookbook work... Decimal Comparisons:
:
: The most common recipe around for comparisons is to use sprintf to cut
: the decimals to size and then compare strings. Seems ugly.```
```
Certainly, but I don't think the situation arises all that frequently
in practice.

: The non-stringification way to do it is usually along the lines of:
:
: if (abs(\$value1 - \$value2) < abs(\$value1 * epsilon))
:
: (From Mastering Algorithms with Perl errata)

You should someday peruse the Ada documentation for this sort of stuff.
It's pretty enlightening (in the Zen sense of feeling smacked upside
the head) about how hard it is to guarantee any particular set of
"real" semantics across unknown machine architectures.

: I'm wondering though, if C<\$value1 == \$value2> is always wrong (or
: almost always wrong) then should it be smarter and:
:
: a. throw a warning
: b. DWIM using overloaded operators (as in reduce precision then compare)
: c. throw a warning but have other comparison operators just for this
: case to make sure you know what you're doing
:
: I'd vote for b., but I don't know enough about the problem domain to
: know if that is safe, and realistically I just want to write the
: cookbook entry rather than start a math-geniuses flame war ;-)

I think I'd vote for

d. Educate users that they almost never want to use == to compare
two numbers on the real number line, however they're represented.
e. Put some rough dwimmery into the ~~ operator instead.

The definition of "rough dwimmery" can be negotiated, but as a form
of definitional handwaving it's probably enough to write examples with.

I welcome input from people who know more about this than I do,
but in the interests of speed, you probably want some way to tell ~~
how many bits of binary mantissa to pay attention to if the exponents
are equal, so you can do most of your work without a horrid conversion
to decimal, or less horribly, subtraction to find a number to compare
to your epsilon.  But by the time you compare exponents, it's possible
that it's cheaper to go ahead and let the hardware do the subtraction
for you.  I'll leave that up to the implementors.

My main point is that the default "slop" should be fairly liberal on
the assumption that the ordinary user has written a fairly sloppy
algorithm.  I'd probably leave about the last 8 bits out of an
ordinary double comparison, but let the user change that pragmatically.

I can see arguments for making the slop a lot bigger than that.
On the other hand, you don't want to make it so big that different
integers start comparing as equal merely because they happen to be big.

On the other other hand, if you know you're storing only integer
values into your floaters, you can safely use == instead of ~~ because
they will always compare equal until you exceed the precision of
the floater.

On the other other other hand, we're gonna all be using 64-bit
computers in a few years, so there will be less demand for putting
large integers into floaters to get around 32-bit limitations.

'Course, then we'll be worrying about the precision of 128-bit floaters...

: Which leads to another question: Are there \$value.precision() and
: \$value.accuracy() methods available for decimals? I'd really rather
: not do the string comparison if it can be avoided, maybe it's just the
: purist in me saying "leave the numbers be" :-)

As the other reply pointed out, it'd be nice to have a data type
that supports these semantics, but they would certainly run slower
than the usual floating-point algorithms do.  Historically the people
doing this sort of stuff would rather have the raw speed and just
sort of hand calculate the uncertainty in their heads, from the basic
rule-of-thumb that additions add uncertainty, while multiplications
multiply uncertainties.

But for models that are trying to be provably accurate rather than
fast, I could see a use for the smarter data type.  For the rest of
us, leaving out about 8 bits for ~~ comparison lets us use algorithms
with a little bit of additive slop, and punishes us a bit when we
use algorithms with a lot of multiplicative slop.  :-)

: Apologies in advance if this is somewhere I missed. I did a lot of searching.

It's not something we've paid much attention to, partly because I *did*
read the Ada spec when it first came out.  :-)

Larry
```