CF> float pi;
CF> [...]
CF> cin >> pi;
CF> [...]
CF> if (pi != 3.142)
As I've said once already in this thread, floating point types in the C and
C++ languages on most platforms, including PCs, use IEEE 754 format. IEEE
754 format is base *two*, not base ten.
The important thing to remember is that it isn't true that a (fractional)
number that has a finite number of digits in one base will have a finite
number of digits in another. The fraction 1/3, for example, has a finite
representation in base 3 ("0.1"), but an infinitely recurring representation
in base 10 ("0.3333333333333333333....").
The value 3.142 is a case in point. It's binary expansion is infinitely
long. The IEEE 754 floating point formats Short Real, Long Real, and
Extended Real (float, double, and long double in the C++ language on certain
platforms) can therefore only hold an *approximation* to the value 3.142.
Moreover, since Short Real only has 23 digits in its significand, whereas
Long Real has 52, this approximation is going to be rounded to different
numbers of binary places in the different floating point types.
This means that in your code, the float variable `pi' has the best
approximation to 3.142 that can fit into a Short Real, whereas the literal
value 3.142 in the `if' statement has the best approximation to 3.142 that
can fit into a Long Real. This is because in the C++ language floating point
literals have, by default, the type `double'.
When your program comes to compare `pi', a float, and `3.142', a double,
using the != operator it promotes them to the same type, promoting the float
to a double in this instance. However, that does *not* magically produce a
double-precision floating-point value that is the best approximation to 3.142
that a double can hold -- because the float variable `pi' *didn't* hold 3.142
in the first place, only an apprixmation to it that had 24 binary digits.
The digits after the 24th that were "lost" when 3.142 was converted to Short
Real for storing into the variable `pi' are lost for good.
Which, in turn, means that `pi' and 3.142 really *aren't* equal, since they
actually contain two different floating-point numbers.
To get around this problem, eliminate the promotion in your code caused by
the != operator. You do this by using a *float* literal:
if (pi != 3.142F)
[ Note for advanced programmers: This assumes, of course, that
istream::operator>>(float&) and your compiler do the same thing when
converting the string "3.142" to a `float' value. Although this happens to
be true of the vast majority of C++ implementations, it isn't always the
case, nor is it required to be. ]
¯ JdeBP ®
--- FleetStreet 1.19 NR
---------------
* Origin: JdeBP's point, using Squish (2:440/4.3)
|