0

Possible Duplicate:
Floating point inaccuracy examples

Im having a problem... When i compile the src, the variable showed isn't the same that i initialized, see it:

#include <iostream>

    using namespace std;

    int main()
    {
      long double mynum = 4.7;
      cout.setf(ios::fixed,ios::floatfield);
      cout.precision( 20 );
      cout << mynum << endl;
    }

And then:

[fpointbin@fedora ~]$ ./a.out 
4.70000000000000017764

How to fix it? I want to "cout" shows 4.700000...

Community
  • 1
  • 1
fpointbin
  • 1,633
  • 3
  • 16
  • 20

5 Answers5

5

Your variable is long double, but the default precision of the literal 4.7 is only double. Since you're printing it as long double, the interpretation chooses to print it with enough significant digits to distinguish it from neighbouring long double values, even though those neighbouring values are not possible doubles.

hmakholm left over Monica
  • 23,074
  • 3
  • 51
  • 73
2

Most platforms, including yours, can only represent those floating point numbers exactly which have a short, finite binary expansion, i.e. which are finite sums of powers of two. 4.7 is not such a number, so it cannot be represented precisely on your platform, and if you demand excessive precision (20 is too much as your mantissa has 64 bits, and log_10(64) is 19.27), then you will inevitably face small errors.

(However, as @Henning says, you are already losing precision when assigning from a (non-long) double; you should write your literal constant as a long double: 4.7L. Then you should only see an error in the 20th digit.)

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
2

floats and doubles are binary floating-point types, i.e. they store a mantissa and an exponent in base 2.

This means that any decimal number that cannot be represented exactly into the finite digits of the mantissa will be approximated; the problem you showed comes from this: 4.7 cannot be represented exactly into the mantissa of a double (the literal 4.7 is of type double, kudos @Henning Makholm for spotting it), so the nearest approximation is used.

To better visualize the problem: in base 3, 2/3 is a number with a finite representation (i.e. 0.23), while in base 10 it is a periodic number (0,6666666...); if you have only a finite space for digits, you'll have to perform an approximation, that will be 0,66666667. That's exactly the same thing here, with the source base being 10 and the "target" base being 2.

If there's a special need to avoid this kind of approximations (e.g. when dealing with decimal amounts of money) special decimal types can be used, that store mantissa and exponent in base 10 (C++ do not provide such type of its own, but there are many decimal classes available on the Net); still, for "normal"/scientific calculations binary FP types are used, because they are much faster and more space-efficient.

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
2

The internal representation of doubles does not allow for an 'exact' representation of 4.7. The 'closest' is 4.70000000000000017764. In reality there is no need to look at a precision of 20 when you have 64 bit doubles. The maximum effective precision is about 15. Try using 12 or so,

cout.precision( 12 );

and you should get what you want to see.

Andrew Stein
  • 12,880
  • 5
  • 35
  • 43
1

Certain numbers cannot be represented in base two. Apparently, 4.7 is one of them. What you're seeing is the closest representable number to 4.7.

There's nothing you can do about this, other than setting the precision to a lower number.

Maxpm
  • 24,113
  • 33
  • 111
  • 170