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.)