gnugo-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnugo-devel] Re: ticket 87, floating point comparison


From: Gunnar Farnebäck
Subject: [gnugo-devel] Re: ticket 87, floating point comparison
Date: Wed, 08 Feb 2006 20:47:26 +0100
User-agent: EMH/1.14.1 SEMI/1.14.3 (Ushinoya) FLIM/1.14.2 (Yagi-Nishiguchi) APEL/10.3 Emacs/21.3 (sparc-sun-solaris2.9) MULE/5.0 (SAKAKI)

Alain wrote:
> http://trac.gnugo.org/gnugo/ticket/87 has been closed as a "won't fix"
> 
> One thing i can do is a fixing patch, replacing all unreliable floating 
> equality test by safe inequality tests:
> if (a == b) 
> replaced by 
> epilon=0.000001
> if (abs(a-b) <= epsilon)

Please don't.

Short reason:
The code becomes more difficult to read without making it any more
robust. Just turn those warnings off.

Long reason:
If you don't know anything about your floating point numbers, no
comparison is guaranteed to be reliable. Maybe a and b happen to
differ by 0.000001 plus or minus an even smaller, platform dependent,
epsilon.

Most of the warnings shown in ticket #87 are about comparisons with
(small) integers, which can be represented exactly, and the compared
values have been computed (or just set) from numbers with an exact
representation. There's nothing unsafe about those comparisons, but
the compiler doesn't know that.

Even worse, just making the proposed change blindly can cause things
to break badly. For example this code in influence.c:

        /* If no influence here before, add the point to the queue for
         * further spreading.
         */
        if (0)
          gprintf("  Spreading %s influence from %1m to %1m, d=%d\n",
                  color_to_string(color), ii, ii + d_ii, d);
        if (working[ii + d_ii] == 0.0) {
          q->queue[queue_end] = ii + d_ii;
          queue_end++;
        }

If the comparison with 0.0 is changed to being less than epsilon, it
might be that influence being spread is much smaller than epsilon and
then it could loop around for a very long time before reaching the
threshold, if ever, severely slowing down the code.

This said, there are tree warnings which are somewhat suspicious,
although mostly harmless:

clock.c(356): remark : floating-point equality and inequality
comparisons are unreliable
    if (time_for_last_move == 0)
                              ^
genmove.c(685): remark : floating-point equality and inequality
comparisons are unreliable
      if (white_score == black_score)
                         ^
play_solo.c(292): remark : floating-point equality and inequality
comparisons are unreliable
        if (result == fabs(score) && winner == dummy)
                      ^

The solution is not necessarily to compare against an epsilon,
however.

/Gunnar




reply via email to

[Prev in Thread] Current Thread [Next in Thread]