Exploring floating-point format
The printBinary( ) function
introduced earlier in this chapter is handy for delving into the internal
structure of various data types. The most interesting of these is the
floating-point format that allows C and C++ to store numbers representing very
large and very small values in a limited amount of space. Although the details
can’t be completely exposed here, the bits inside of
floats and
doubles are divided into three regions: the
exponent, the mantissa, and the sign bit; thus it stores the values using
scientific notation. The following program allows you to play around by printing
out the binary patterns of various floating point numbers so you can deduce for
yourself the scheme used in your compiler’s floating-point format (usually
this is the IEEE standard for floating point numbers, but
your compiler may not follow that):
//: C03:FloatingAsBinary.cpp
//{L} printBinary
//{T} 3.14159
#include "printBinary.h"
#include <cstdlib>
#include <iostream>
using namespace std;
int main(int argc, char* argv[]) {
if(argc != 2) {
cout << "Must provide a number" << endl;
exit(1);
}
double d = atof(argv[1]);
unsigned char* cp =
reinterpret_cast<unsigned char*>(&d);
for(int i = sizeof(double)-1; i >= 0 ; i -= 2) {
printBinary(cp[i-1]);
printBinary(cp[i]);
}
} ///:~
First, the program guarantees that
you’ve given it an argument by checking the value of argc, which is
two if there’s a single argument (it’s one if there are no
arguments, since the program name is always the first element of argv).
If this fails, a message is printed and the Standard C Library function
exit( ) is called to terminate the program.
The program grabs the argument from the
command line and converts the characters to a double using
atof( ). Then the double is treated as an
array of bytes by taking the address and casting it to an unsigned char*.
Each of these bytes is passed to printBinary( ) for
display.
This example has been set up to print the
bytes in an order such that the sign bit appears first – on my machine.
Yours may be different, so you might want to re-arrange the way things are
printed. You should also be aware that floating-point formats are not trivial to
understand; for example, the exponent and mantissa are not generally arranged on
byte boundaries, but instead a number of bits is reserved for each one and they
are packed into the memory as tightly as possible. To truly see what’s
going on, you’d need to find out the size of each part of the number (sign
bits are always one bit, but exponents and mantissas are of differing sizes) and
print out the bits in each part separately.