14.1: When I set a float variable to, say, 3.1, why is printf printing
it as 3.0999999?
A: Most computers use base 2 for floating-point numbers as well as
for integers. In base 2, one divided by ten is an infinitely-
repeating fraction (0.0001100110011...), so fractions such as
3.1 (which look like they can be exactly represented in decimal)
cannot be represented exactly in binary. Depending on how
carefully your compiler's binary/decimal conversion routines
(such as those used by printf) have been written, you may see
discrepancies when numbers (especially low-precision floats) not
exactly representable in base 2 are assigned or read in and then
printed (i.e. converted from base 10 to base 2 and back again).
See also question 14.6.
...
14.4: My floating-point calculations are acting strangely and giving
me different answers on different machines.
A: First, see question 14.2 above.
If the problem isn't that simple, recall that digital computers
usually use floating-point formats which provide a close but by
no means exact simulation of real number arithmetic. Underflow,
cumulative precision loss, and other anomalies are often
troublesome.
Don't assume that floating-point results will be exact, and
especially don't assume that floating-point values can be
compared for equality. (Don't throw haphazard "fuzz factors"
in, either; see question 14.5.)
These problems are no worse for C than they are for any other
computer language. Certain aspects of floating-point are
usually defined as "however the processor does them" (see also
question 11.34), otherwise a compiler for a machine without the
"right" model would have to do prohibitively expensive
emulations.
This article cannot begin to list the pitfalls associated with,
and workarounds appropriate for, floating-point work. A good
numerical programming text should cover the basics; see also the
references below.
References: Kernighan and Plauger, _The Elements of Programming
Style_ Sec. 6 pp. 115-8; Knuth, Volume 2 chapter 4; David
Goldberg, "What Every Computer Scientist Should Know about
Floating-Point Arithmetic".
...
14.13: I'm having trouble with a Turbo C program which crashes and says
something like "floating point formats not linked."
A: Some compilers for small machines, including Borland's
(and Ritchie's original PDP-11 compiler), leave out certain
floating point support if it looks like it will not be needed.
In particular, the non-floating-point versions of printf()
and scanf() save space by not including code to handle %e, %f,
and %g. It happens that Borland's heuristics for determining
whether the program uses floating point are insufficient,
and the programmer must sometimes insert a dummy call to a
floating-point library function (such as sqrt(); any will
do) to force loading of floating-point support. (See the
comp.os.msdos.programmer FAQ list for more information.)