From: Sven Peeters on
Hi,

I've got a problem with the atof function when using a certain string.

Example Code ( We use VS6 ) :

/* atof example */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main ()
{
double n;
char *s;
s = "0.2100000";
n = atof(s);
return 0;
}

If you look in the watch window, the value of n is 0.20999999 instead if 0.21.
This gives me some rounding errors further down in my program.
Unfortunately 21 is the most common used VATrate in my country.

How can I sove this that atof converts correctly.

Sven Peeters
Belgium
From: Bruno van Dooren on
> If you look in the watch window, the value of n is 0.20999999 instead if
> 0.21.
> This gives me some rounding errors further down in my program.
> Unfortunately 21 is the most common used VATrate in my country.

you get 0.20999999 because 0.21 simply does not exist as a floating point
number.
everything behind the decimal symbol is an approximation that is guaranteed
to be correct up to n digits behind the decimal place, where n depends on
your format. double is more precise than float.

search google for 'what every programmer needs to know about float
arithmetic' and you'll get a whole lot of articles with precise
explanations.

--

Kind regards,
Bruno.
bruno_nos_pam_van_dooren(a)hotmail.com
Remove only "_nos_pam"


From: Alex Blekhman on
Sven Peeters wrote:
> If you look in the watch window, the value of n is
> 0.20999999 instead if 0.21. This gives me some rounding
> errors further down in my program.

Floating point calculations are inexact due to binary
floating point representation in computers. You have
sevearal choices:

1. Manage all calculations in floating point and round
results from time to time.
2. Use integers to represent currency values. Look for
CURRENCY and VARIANT in MSDN. You can take source of
COleCurrency MFC class as example.
3. Buy expensive third party library for financial
calculations.

HTH
Alex


From: David Webber on

"Sven Peeters" <SvenPeeters(a)discussions.microsoft.com> wrote in message
news:245352A2-4FEF-407A-B208-2DBAD3455046(a)microsoft.com...

> If you look in the watch window, the value of n is 0.20999999 instead if
> 0.21.
> This gives me some rounding errors further down in my program.
> Unfortunately 21 is the most common used VATrate in my country.
>
> How can I sove this that atof converts correctly.

It *is* converting correctly.

If you use doubles, you will get it right to around 16 sig figs, and it
can't do better.

When you print the final answer just round everything to two decimal places.
Unless you are doing extremely long winded calculations, the rounding error
won't propagate that far. Schematically something like:

double result = ...;
int n = nearest_integer( result * 100 );
printf( "%d.%02d", n/100, n%100 );

It's much easier than trying to hold floating point numbers to an accuracy
greater than the format can manage!

Dave
--
David Webber
Author MOZART the music processor for Windows -
http://www.mozart.co.uk
For discussion/support see
http://www.mozart.co.uk/mzusers/mailinglist.htm




From: David Webber on

"Alex Blekhman" <tkfx.N05P4M(a)yahoo.com> wrote in message
news:eVqjgoXLGHA.904(a)TK2MSFTNGP10.phx.gbl...

> Floating point calculations are inexact due to binary floating point
> representation in computers. You have sevearal choices:

Let me just add that floating point representations of numbers are
intrinsically inexact - not just because of the computer representation.

1/3 is a precise number

0.333333333... to any finite number of places is an approximation.

[Of course only rational numbers can be stored exactly as fractions.
Irrationals like sqrt(2) cannot be.]

The normal scientific convention is that 0.21 is a number somewhere between
0.205 and 0.215

And that 0.210 is a number between 0.2095 and 0.2105

And that successive trailing zeroes imply a greater and greater precision.
The computer's error of 1 in the last stored sig fig is entirely consistent
with this.

The problem arises if you try to interpret 0.21 as meaning 0.21 followed by
an infinite number of trailing zeroes (or the exact rational number 21/100).
This spurious exactness is not invariant under a change of arithmetic base.

For example in a ternary representation, where we use digits 0,1,2, to count
1, 2, 10, 11, 12, 20, ... the number

0.10000000000000000000...

is a representation of one third, which is in decimal:

0.33333333333333333333...

In the first case the trailing zeroes go on for ever, and in the second the
trailing threes go on forever. There's no essential difference.

But if you (foolishly) take the view that 0.1 is "exactly one third" in the
first case, then you have a number which you believe to be "exact" in
ternary but which cannot be represented "exactly" in decimal. So (I
imagine) it is that if you assume 0.21 is "exact" in decimal, it ghas no
"exact" hexademial representation.

Much better to come to terms with floating point representations as being
inexact in *all* cases, and *not* just because of the binary representation
used by computers. It derives from the fact that for any pair of different
real numbers there is always another one, different from both, between them
(which is not a property of the integers). It is a subject which predated
computers by a long long way!

Dave
--
David Webber
Author MOZART the music processor for Windows -
http://www.mozart.co.uk
For discussion/support see
http://www.mozart.co.uk/mzusers/mailinglist.htm