This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: Floats different printing than doubles?
- To: Christopher Denney <chris at isis dot bbmbc dot org>
- Subject: Re: Floats different printing than doubles?
- From: Geoff Keating <geoffk at cygnus dot com>
- Date: 24 Aug 2000 13:37:19 -0700
- CC: gcc-bugs at gcc dot gnu dot org
- References: <B5CAA9CA.11CF3%chris@isis.bbmbc.org>
Christopher Denney <chris@isis.bbmbc.org> writes:
> I wrote a simple cash register program (c++) that was supposed to print the
> input number multiplied by 1.03 rounded to two decimal places.
>
> I failed to get the correct output when the type was double, but it works
> fine when the type is float. It seems to have difficulty with rounding .055
> to .06, but it will round .056 to .06. Float works fine in all cases I
> tested.
>
> I am running gcc-2.95.2 on a sun sparc with solaris 2.5.1, no extra config
> flags.
> -------------------------------------------------------------
> // cash.cpp
> #include <iostream>
>
> int main()
> {
> float val1; // Input Value
> float res; // Result
>
> cout << "\nCash Register Running\n";
> cout << "Please Input Value: ";
> cin >> val1;
> res = val1 * 1.03;
> cout.precision(2);
> cout.flags(ios::fixed | ios::showpoint);
> cout << "\nTotal Sale = " << res << "\n\n";
> cout << "Thank you. Have a nice day.\n" << endl;
>
> return 0;
> }
> -------------------------------------------------------------
>
> compiled with:
> $ c++ cash.cpp
> run with:
> $ a.out
> input of 18.5 gives output of 19.06
> change the float types to double and input of 18.5 gives output of 19.05
>
> This I thought was wrong. :)
This is caused by rounding. In binary, 1.03 is
1.00000*11110101110000101000* with the bit between '*'s repeating
forever; you've written plain '1.03', so it gets to be a double, which
makes it: 1.00000111101011100001010001111010111000010100011110110
Multiply this by 18.5 (which is exactly representable in binary), you
get 10011.00001110000101000111101011100001010001111010111000111
exactly, then if you round that to 'float' you get
10011.0000111000010100100 which was rounded up; if you round it to
'double' you get
10011.0000111000010100011110101110000101000111101011100 which is
rounded down. The 'true' answer is 19.55 which is
10011.0000*11100001010001111010* with the bit between the *s repeating.
So one of these is a little bit below 19.55, so it gets rounded down
to 19.5, the other one a little above so it gets rounded up.
--
- Geoffrey Keating <geoffk@cygnus.com>