delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2001/09/10/17:13:05

Mailing-List: contact cygwin-help AT sourceware DOT cygnus DOT com; run by ezmlm
List-Subscribe: <mailto:cygwin-subscribe AT sources DOT redhat DOT com>
List-Archive: <http://sources.redhat.com/ml/cygwin/>
List-Post: <mailto:cygwin AT sources DOT redhat DOT com>
List-Help: <mailto:cygwin-help AT sources DOT redhat DOT com>, <http://sources.redhat.com/ml/#faqs>
Sender: cygwin-owner AT sources DOT redhat DOT com
Delivered-To: mailing list cygwin AT sources DOT redhat DOT com
To: Marco Craveiro <soupdragon AT clix DOT pt>
Cc: cygwin AT cygwin DOT com
Subject: Re: atof returns a value that is slightly greater than the original string
References: <1000153353 DOT 1101 DOT 8 DOT camel AT darkroom>
From: James Youngman <jay AT gnu DOT org>
Date: 10 Sep 2001 22:12:00 +0100
In-Reply-To: <1000153353.1101.8.camel@darkroom>
Message-ID: <x61ylevjhb.fsf@no-such-thing-as-a.free-lunch.demon.co.uk>
Lines: 67
User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7
MIME-Version: 1.0

Marco Craveiro <soupdragon AT clix DOT pt> writes:

> int main (void)
> {
> float f = atof ("695.40");
> 
> cout << f;
> }
> 
> (gdb) p f
> $2 = 695.400024         ----> after assignment

> 
> since I need this the data to generate a sum, the sum ends up a bit off
> because of this. and unfortunatelly, because there is so many people
> with the #include problem, its impossible to search the web properly.
> I'm sure its something i'm doing (or not doing), just can't see
> what...

This is not a bug in Cygwin.  This is because of the fact that a float
is almost never an exact representation of a decimal number.

Each bit in a float represents a power of two which is either added to
the total value, or not.  

Hence 695 can be represented exactly in binary as 1010110111, but 
the extra 0.4 is a problem.   Using a fairly large number of binary
digits, you can get quite close :-

shell $ ( echo obase=2; echo scale=30; echo 6954/10 ) | bc

1010110111.011001100110011001100110011001100110011001100110011001100\
1100110011001100110011001100110011001100110


...but of course this is not exact (the backslashes here are just for
readability).  

Unfortunately there are only 32 bits of data in a float, so the
approximation used in a float is even less.   If we change your
program to use more precise types we get the following results :-

float             695.400024
double            695.39999999999998
long double       695.39999999999997726263245567679405

If you want more precision still, you can use Bruno Haible's excellent
CLN library (which is written in C++ and provides a good C++ API for
extended precision arithmetic, and was originally written in order to
provide Common Lisp bignum support).

If you need "infinite" precision, CLN also offers a 'rational'
representation which would represent "695.4" as "6954/10".  However,
as you continue to calculate with rational values, the large number of
digits used on the top and bottom of the fraction can use lots of RAM
up.  There are also lots of things you can't use rational arithmetic
for, for example trigonometry or root extraction.

The other place to look for an explanation of this problem is the FAQ
lists for the comp.lang.c and comp.lang.c++ newsgroups. See
ftp://rtfm.mit.edu/.


-- 
James Youngman
Manchester, UK.  +44 161 226 7339
PGP (GPG) key ID for <jay AT gnu DOT org> is 64A95EE5 (F1B83152).

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Bug reporting:         http://cygwin.com/bugs.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

- Raw text -


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