[prev] [up] [overview] [next]

Section 15. Floating Point

15.1: My floating-point calculations are acting strangely and giving me different answers on different machines.

First, make sure that you have #included <math.h>, and correctly declared other functions returning double.

If the problem isn't that simple, recall that most digital computers 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.)

These problems are no worse for C than they are for any other computer language.  Floating-point semantics are usually defined as "however the processor does them;" 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 programming text should cover the basics.

References: EoPS Sec. 6 pp. 115-8.

15.2: I'm trying to do some simple trig, and I am #including <math.h>;, but I keep getting "undefined: _sin" compilation errors.

Make sure you're linking with the correct math library.  For instance, under Unix, you usually need to use the -lm option, and at the end of the command line, when compiling/linking. See also question 12.14.

15.3: Why doesn't C have an exponentiation operator?

Because few processors have an exponentiation instruction. Instead, you can #include <math.h> and use the pow() function, although explicit multiplication is often better for small positive integral exponents.

References: ANSI Sec. 4.5.5.1 .

15.4: How do I round numbers?

The simplest and most straightforward way is with code like

        (int)(x + 0.5)

This won't work properly for negative numbers, though.

15.5: How do I test for IEEE NaN and other special values?

Many systems with high-quality IEEE floating-point implementations provide facilities (e.g. an isnan() macro) to deal with these values cleanly, and the Numerical C Extensions Group (NCEG) is working to formally standardize such facilities. A crude but usually effective test for NaN is exemplified by

        #define isnan(x) ((x) != (x))

although non-IEEE-aware compilers may optimize the test away.

15.6: I'm having trouble with a Turbo C program which crashes and says something like "floating point formats not linked."

Some compilers for small machines, including Turbo C (and Ritchie's original PDP-11 compiler), leave out 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 Turbo C's heuristics for determining whether the program uses floating point are insufficient, and the programmer must sometimes insert an extra, explicit call to a floating-point library routine to force loading of floating-point support.


[prev] [up] [overview] [next]