delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1997/04/29/11:39:36

From: "John M. Aldrich" <fighteerNO AT SPAMcs DOT com>
Newsgroups: comp.os.msdos.djgpp
Subject: Re: Floating point bug???
Date: Mon, 28 Apr 1997 10:49:37 +0000
Organization: Two pounds of chaos and a pinch of salt
Lines: 66
Message-ID: <336480C1.37C2@SPAMcs.com>
References: <qb2z7BAkbVZzEwJA AT jenkinsdavid DOT demon DOT co DOT uk>
Reply-To: fighteer AT cs DOT com
NNTP-Posting-Host: ppp103.cs.com
Mime-Version: 1.0
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp

David Jenkins wrote:
> 
> I'm having some trouble with comparing floats to integers.
> The following source uses an integer target variable and a floating
> point current variable.
> I set the target to a random value the change the value of current
> depending on whether it is lower or higher than the target variable.
> 
> It seems simple a enough thing to ask my program to do. BUT it won't,
> when it reaches "target" weird things happen. The "current" stays an
> offset according to SPEED away from the "target".
> I've even tried changing the "target" to a float.
> Is there some function in C that I don't know about, I'm only a couple
> of months old. ;-)

Your problem is the cumulative error introduced by the lack of precision
of floating point variables.  If you change the print specifier to
%.10f, you'll see this.  By the time the value of current gets to the
vicinity of 37, its actual value is 36.9000091553.  Naturally, adding
one to this makes the value higher than 37, so the second if statement
is triggered and subtracts 0.1 from it.  You get stuck in an infinite
repetition because of the imprecision of floating point numbers.

There's no easy way around the problem, because it even persists when
you change the precision of current to double or long double.  It's the
repetitive additions and subtractions that cause the problem, not the
comparison to an integer.  You may want to try "pruning" the value by
using something like this:

    current = floor( current * 100.0 + 0.5 ) / 100.0;

Do this after each update to current and your program will work as
intended (I just tested it myself).  Some additional comments, though:

 - rand() is declared in <stdlib.h>
 - You should call srand() if you want to initialize the random number
generator with a nonzero seed.  Otherwise, you'll get exactly the same
results every time you run your program.
 - random() is a much better RNG than rand().  Use srandom() to seed it.
 - A good seed is the clock value, obtained via time().  So the most
commonly used way to seed the RNG is this:
    srandom( (int) time( 0 ) );
 - Your if block within the loop is somewhat ambiguous.  It might be
better if you did it this way:

        if (current < target)
            current += SPEED;
        else if (current > target)
            current -= SPEED;
        else if (current == target)
            target = rand() % 100;

   That way, only one of the above items is performed at each pass
through the loop.
 - If you want to delay your program, why not just use delay()?

hth!
-- 
John M. Aldrich, aka Fighteer I <fighteer AT cs DOT com>

-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS d- s+:- a-->? c++>$ U@>++$ p>+ L>++ E>++ W++ N++ o+>++ K? w(---)
O- M-- V? PS+ PE Y+ PGP- t+(-) 5- X- R+(++) tv+() b+++ DI++ D++ G>++
e(*)>++++ h!() !r !y+()
------END GEEK CODE BLOCK------

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019