The C++ Double-Precision Floating Point Variable

By Stephen R. Davis

The standard floating-point variable in C++ is its larger sibling, the double-precision floating point or simply double. You declare a double-precision floating point as follows:

double dValue1;
double dValue2 = 1.5;

The limitations of the int variable in C++ are unacceptable in some applications. Fortunately, C++ understands decimal numbers that have a fractional part. (Mathematicians call these real numbers.) In C++, decimal numbers are called floating-point numbers or simply floats. This is because the decimal point can float around from left to right to handle fractional values.

Floating-point variables come in two basic flavors in C++. The small variety is declared by using the keyword float as follows:

float fValue1;        // declare a floating point
float fValue2 = 1.5;  // initialize it at declaration

Solving the truncation problem

To see how the double fixes our truncation problem, consider the average of three floating-point variables dValue1, dValue2, and dValue3 given by the formula

double dAverage = dValue1/3.0 + dValue2/3.0 + dValue3/3.0;

Assume, once again, the initial values of 1.0, 2.0, and 2.0. This renders the expression just given here as equivalent to

double dAverage = 1.0/3.0 + 2.0/3.0 + 2.0/3.0;

which is, in turn, equivalent to

double dAverage = 0.333... + 0.6666... + 0.6666...;

resulting in a final value of

double dAverage = 1.666...;

The preceding expressions are written as though there were an infinite number of sixes after the decimal point. In fact, this isn’t the case. The accuracy of a double is limited to about 14 significant digits. The difference between 1.666666666666 and 1 2/3 is small, but not zero.

When an integer is not an integer

C++ assumes that a number followed by a decimal point is a floating-point constant. Thus it assumes that 2.5 is a floating point. This decimal-point rule is true even if the value to the right of the decimal point is zero. Thus 3.0 is also a floating point. The distinction between 3 and 3.0 looks small to you, but not to C++.

Actually, you don’t have to put anything to the right of the decimal point. Thus C++ also sees 3. as a double. However, it’s considered good style to include the 0 after the decimal point for all floating-point constants.

Computer geeks will be interested to know that the internal representations of 3 and 3.0 are totally different (yawn). More importantly, the constant int 3 is subject to int rules, whereas 3.0 is subject to the rules of floating-point arithmetic.

Thus you should try to avoid expressions like the following:

double dValue = 1.0;
double dOneThird = dValue/3;

Technically this is what is known as a mixed-mode expression because dValue is a double but 3 is an int. Okay, C++ is not a total idiot — it knows what you want in a case like this, so it converts the 3 to a double and performs floating-point arithmetic.

There’s a name for this bit of magic: C++ promotes the int 3 to a double. C++ also allows you to assign a floating-point result to an int variable:

int nValue = dValue / 3.0;

Assigning a double to an int is known as a demotion.

Some C++ compilers generate a warning when promoting a variable. All C++ compilers generate a warning (or error) when demoting a result due to the loss of precision.

You should get in the habit of avoiding mixed-mode arithmetic. If you have to change the type of an expression, do it explicitly by using a cast, as in the following example:

void fn(int nArg)
{
    // calculate one third of nArg; use a cast to
    // promote it to a floating point
    double dOneThird = (double)nArg / 3.0;
    // ...function continues on

The naming convention of starting double-precision double variables with the letter d is used here. That is merely a convention. You can name your variables any way you like — C++ doesn’t care.