CrossWorks C allows you to choose whether the **double** data
type uses the IEC 60559 32-bit or 64-bit format. The following sections describe
the details of why you would want to choose a 32-bit **double** rather
than a 64-bit **double** in many circumstances.

Many users are surprised when using **float** variables exclusively
that sometimes their calculations are compiled into code that calls for **double** arithmetic.
They point out that the C standard allows **float** arithmetic
to be carried out only using **float** operations and not to automatically
promote to the **double** data type of classic K&R C.

This is valid point. However, upon examination, even the simplest calculations
can lead to **double** arithmetic. Consider:

// Compute sin(2x) float sin_two_x(float x) { return sinf(2.0 * x); }

This looks simple enough. We're using the **sinf** function which
computes the sine of a **float** and returns a **float** result.
There appears to be no mention of a **double** anywhere, yet the
compiler generates code that calls **double** support routines—but
why?

The answer is that the constant **2.0** is a **double** constant,
not a **float** constant. That is enough to force the compiler
to convert both operands of the multiplication to **double** format,
perform the multiplication in **double** precision, and then convert
the result back to **float** precision. To avoid this surprise,
the code should have been written:

// Compute sin(2x) float sin_two_x(float x) { return sinf(2.0F * x); }

This uses a single precision floating-point constant **2.0F**.
It's all too easy to forget to correctly type your floating-point constants,
so if you compile your program with **double** meaning the same
as **float**, you can forget all about adding the '**F**'
suffix to your floating point constants.

As an aside, the C99 standard is very strict about the way that floating-point
is implemented and the latitude the compiler has to rearrange and manipulate
expressions that have floating-point operands. The compiler cannot second-guess
user intention and use a number of useful mathematical identities and algebraic
simplifications because in the world of IEC 60559 arithmetic many algebraic
identities, such as **x * 1 = x**, do not hold when **x** takes
one of the special values NaN, infinity, or negative zero.

Floating-point constants are not the only silent way that **double** creeps
into your program. Consider this:

void write_results(float x) { printf("After all that x=%f\\n", x); }

Again, no mention of a **double** anywhere, but **double** support
routines are now required. The reason is that ISO C requires that **float** arguments
are promoted to **double** when they are passed to the non-fixed
part of variadic functions such as **printf**. So, even though
your application may never mention **double**, **double** arithmetic
may be required simply because you use **printf** or one of its
near relatives.

If, however, you compile your code with 32-bit doubles, then there is no requirement
to promote a **float** to a **double** as they share
the same internal format.

If your application requires very accurate floating-point, more precise than
the seven decimal digits supported by the **float** format, then
you have little option but to use **double** arithmetic as there
is no simple way to increase the precision of the **float** format.
The **double** format delivers approximately 15 decimal digits
of precision.