Exercise 3-29 (Print groups of bits of floats in C/C++)
Chapter_3 Exercise_3-28 | PointerIncrement Exercise_3-30 |
Exercise 3-29 TCP1, p. 230
Exercise 3-29. (Challenging) Modify FloatingAsBinary.cpp (see ch3-FloatBinary) so that it prints out each part of the double as a separate group of bits. You’ll have to replace the calls to printBinary() with your own specialized code (which you can derive from printBinary() in order to do this), and you’ll also have to look up and understand the floating-point format along with the byte ordering for your compiler (this is the challenging part).
CONTENTS: floatbinary2.c FloatBinary2.cpp
floatbinary2.c download
#include <stdio.h> // for printf(), putchar()
#include <stdlib.h> // for atof(), exit()
void printFloatBinary(float); // Display a float in binary
void printDoubleBinary(double); // Display a double in binary
void printLongDoubleBinary(long double); // Display a long double in binary
int main(int argc, char* argv[])
{
if(argc != 2)
{
printf("Must provide a number\n");
exit(1); // out of main(), end program; return value 1 signals an error
}
int i;
double d = atof(argv[1]);
float f = d; // implicit cast (restrictive)
printFloatBinary(f);
printDoubleBinary(d);
long double ld = d; // implicit cast (extended)
printLongDoubleBinary(ld);
return 0; // normal return value for main(), signals no errors
}
void printFloatBinary(float f) // Display a float in binary
{ // we assume `float' has 32 bits: 1 for sign, 8 for exp, 23 for mantissa
int i = 7; // first (most significant) position in a byte
int j = sizeof(float)-1; // first (most significant) byte (3) of a float
unsigned char* cp = (unsigned char*)(&f); // we assume sizeof(char) = 1
unsigned char val = cp[j]; // most significant byte of `f'
// first print the sign (bit 31):
if(val & (1 << i)) // set (1) bit for negative numbers
{putchar('1');}
else {putchar('0');} // 0 bit for positive numbers
putchar(' '); // separate the sign from the rest of `f' in binary
for(i = 6; i >= 0; i--) // the most significant 7 bits of the exponent
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{putchar('1');}
else {putchar('0');} // 0 bit
}
j--; // move to the next (less significant) byte of `f' (2)
val = cp[j];
i = 7; // first (most significant) position in a byte
// the least significant bit of the exponent (bit 23):
if(val & (1 << i)) // set (1) bit
{putchar('1');}
else {putchar('0');} // 0 bit
putchar(' '); // separate exponent from mantissa (last 23 bits)
for(i = 6; i >= 0; i--) // the most significant 7 bits of mantissa
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{putchar('1');}
else {putchar('0');} // 0 bit
}
while (--j >= 0) // last (least significant) 2 bytes of `f' (1, 0)
{ // the rest of mantissa (16 bits)
val = cp[j];
for(i = 7; i >= 0; i--)
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{putchar('1');}
else {putchar('0');} // 0 bit
}
}
putchar('\n');
}
void printDoubleBinary(double d) // Display a double in binary
{ // we assume `double' has 64 bits: 1 for sign, 11 for exp, 52 for mantissa
int i = 7; // first (most significant) position in a byte
int j = sizeof(double)-1; // first (most significant) byte (7) of a double
unsigned char* cp = (unsigned char*)(&d); // we assume sizeof(char) = 1
unsigned char val = cp[j]; // most significant byte of `d'
// first print the sign (bit 63):
if(val & (1 << i)) // set (1) bit for negative numbers
{putchar('1');}
else {putchar('0');} // 0 bit for positive numbers
putchar(' '); // separate the sign from the rest of `d' in binary
for(i = 6; i >= 0; i--) // the most significant 7 bits of the exponent
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{putchar('1');}
else {putchar('0');} // 0 bit
}
j--; // move to the next (less significant) byte of `d' (6)
val = cp[j];
for(i = 7; i >= 4; i--) // the least significant 4 bits of the exponent
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{putchar('1');}
else {putchar('0');} // 0 bit
}
putchar(' '); // separate exponent from mantissa (last 52 bits)
for(; i >= 0; i--) // the most significant 4 bits of mantissa (3, 2, 1, 0)
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{putchar('1');}
else {putchar('0');} // 0 bit
}
while (--j >= 0) // last (least significant) 6 bytes of `d' (5, 4, ..., 0)
{ // the rest of mantissa (48 bits)
val = cp[j];
for(i = 7; i >= 0; i--)
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{putchar('1');}
else {putchar('0');} // 0 bit
}
}
putchar('\n');
}
void printLongDoubleBinary(long double ld) // Display a long double in binary
{ // extended precision, 80 bits: 1 sign, 15 exp, 1 int part, 63 fraction
int i; // count bits of a byte
int j = sizeof(long double)-1; // first byte (15) of a long double
unsigned char* cp = (unsigned char*)(&ld); // we assume sizeof(char) = 1
unsigned char val; // for the bytes of `ld'
for(; j >=10; j--) // first 6 bytes are garbage (48 bits)
{ // we assume sizeof(long double) = 16 (128 = 48 + 80 bits)
val = cp[j];
for(i = 7; i >= 0; i--)
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{putchar('1');}
else {putchar('0');} // 0 bit
}
}
putchar(' '); // separate garbage (48 bits) from the rest (80 bits)
val = cp[j]; // byte 9 of `ld' (the most significant of the last 10 bytes)
i = 7; // first (most significant) position in a byte
// first print the sign (bit 79):
if(val & (1 << i)) // set (1) bit for negative numbers
{putchar('1');}
else {putchar('0');} // 0 bit for positive numbers
putchar(' '); // separate the sign from the rest of `ld' in binary
for(i = 6; i >= 0; i--) // the most significant 7 bits of the exponent
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{putchar('1');}
else {putchar('0');} // 0 bit
}
j--; // move to the next (less significant) byte of `ld' (8)
val = cp[j];
for(i = 7; i >= 0; i--) // the least significant 8 bits of the exponent
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{putchar('1');}
else {putchar('0');} // 0 bit
}
putchar('\n'); // separate exponent from mantissa (last 64 bits)
j--; // move to the next (less significant) byte of `ld' (7)
val = cp[j];
i = 7;
// print the integer part of mantissa (bit 63):
if(val & (1 << i)) // set (1) bit
{putchar('1');}
else {putchar('0');} // 0 bit
putchar(' '); // separate integer part from fraction (63 bits)
i = 6;
// print the first (most significant) bit of the fraction (bit 62):
if(val & (1 << i)) // set (1) bit
{putchar('1');}
else {putchar('0');} // 0 bit
putchar(' '); // separate first bit from the rest of the fraction (62 bits)
for(i = 5; i >= 0; i--) // next most significant 6 bits of the fraction
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{putchar('1');}
else {putchar('0');} // 0 bit
}
while (--j >= 0) // last (least significant) 7 bytes of `ld' (6, 5, ..., 0)
{ // the rest of the fraction and of mantissa (56 bits)
val = cp[j];
for(i = 7; i >= 0; i--)
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{putchar('1');}
else {putchar('0');} // 0 bit
}
}
putchar('\n');
}
/*
gcc floatbinary2.c -o floatbinary2
./floatbinary2
Must provide a number
./floatbinary2 0 1
Must provide a number // exactly one number
./floatbinary2 0
0 00000000 00000000000000000000000 // single-precision floating-point
0 00000000000 0000000000000000000000000000000000000000000000000000 // double
000000000000000000000000000000000000000000000000 0 000000000000000 // long
0 0 00000000000000000000000000000000000000000000000000000000000000 // double
./floatbinary2 1
0 01111111 00000000000000000000000
0 01111111111 0000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000 0 011111111111111
1 0 00000000000000000000000000000000000000000000000000000000000000
./floatbinary2 2
0 10000000 00000000000000000000000
0 10000000000 0000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000 0 100000000000000
1 0 00000000000000000000000000000000000000000000000000000000000000
./floatbinary2 3
0 10000000 10000000000000000000000
0 10000000000 1000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000 0 100000000000000
1 1 00000000000000000000000000000000000000000000000000000000000000
./floatbinary2 4
0 10000001 00000000000000000000000
0 10000000001 0000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000 0 100000000000001
1 0 00000000000000000000000000000000000000000000000000000000000000
./floatbinary2 0.1
0 01111011 10011001100110011001101
0 01111111011 1001100110011001100110011001100110011001100110011010
000000000000000000000000000000000000000000000000 0 011111111111011
1 1 00110011001100110011001100110011001100110011001101000000000000
./floatbinary2 0.2
0 01111100 10011001100110011001101
0 01111111100 1001100110011001100110011001100110011001100110011010
000000000000000000000000000000000000000000000000 0 011111111111100
1 1 00110011001100110011001100110011001100110011001101000000000000
./floatbinary2 -0.1
1 01111011 10011001100110011001101
1 01111111011 1001100110011001100110011001100110011001100110011010
000000000000000000000000000000000000000000000000 1 011111111111011
1 1 00110011001100110011001100110011001100110011001101000000000000
./floatbinary2 -.2
1 01111100 10011001100110011001101
1 01111111100 1001100110011001100110011001100110011001100110011010
000000000000000000000000000000000000000000000000 1 011111111111100
1 1 00110011001100110011001100110011001100110011001101000000000000
./floatbinary2 15
0 10000010 11100000000000000000000
0 10000000010 1110000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000 0 100000000000010
1 1 11000000000000000000000000000000000000000000000000000000000000
./floatbinary2 15.1
0 10000010 11100011001100110011010
0 10000000010 1110001100110011001100110011001100110011001100110011
000000000000000000000000000000000000000000000000 0 100000000000010
1 1 11000110011001100110011001100110011001100110011001100000000000
./floatbinary2 15.2
0 10000010 11100110011001100110011
0 10000000010 1110011001100110011001100110011001100110011001100110
000000000000000000000000000000000000000000000000 0 100000000000010
1 1 11001100110011001100110011001100110011001100110011000000000000
./floatbinary2 15.3
0 10000010 11101001100110011001101
0 10000000010 1110100110011001100110011001100110011001100110011010
000000000000000000000000000000000000000000000000 0 100000000000010
1 1 11010011001100110011001100110011001100110011001101000000000000
*/
Note: See Single-precision, Double-precision, and Extended_precision (for long_double) floating-point formats, on Wikipedia. See also ch3-FloatBinary.
FloatBinary2.cpp download
#include <iostream>
#include <cstdlib> // for atof(), exit()
using std::cout;
using std::endl;
void printFloatBinary(float); // Display a float in binary
void printDoubleBinary(double); // Display a double in binary
void printLongDoubleBinary(long double); // Display a long double in binary
int main(int argc, char* argv[])
{
if(argc != 2)
{
cout << "Must provide a number" << endl;
exit(1); // out of main(), end program; return value 1 signals an error
}
double d = atof(argv[1]);
float f = d; // implicit cast (restrictive)
printFloatBinary(f);
printDoubleBinary(d);
long double ld = d; // implicit cast (extended)
printLongDoubleBinary(ld);
return 0; // normal return value for main(), signals no errors
}
void printFloatBinary(float f) // Display a float in binary
{ // we assume `float' has 32 bits: 1 for sign, 8 for exp, 23 for mantissa
int i = 7; // first (most significant) position in a byte
int j = sizeof(float)-1; // first (most significant) byte (3) of a float
unsigned char* cp = reinterpret_cast<unsigned char*>(&f); // we assume sizeof(char) = 1
unsigned char val = cp[j]; // most significant byte of `f'
// first print the sign (bit 31):
if(val & (1 << i)) // set (1) bit for negative numbers
{cout << '1';}
else {cout << '0';} // 0 bit for positive numbers
cout << ' '; // separate the sign from the rest of `f' in binary
for(i = 6; i >= 0; i--) // the most significant 7 bits of the exponent
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{cout << '1';}
else {cout << '0';} // 0 bit
}
j--; // move to the next (less significant) byte of `f' (2)
val = cp[j];
i = 7; // first (most significant) position in a byte
// the least significant bit of the exponent (bit 23):
if(val & (1 << i)) // set (1) bit
{cout << '1';}
else {cout << '0';} // 0 bit
cout << ' '; // separate exponent from mantissa (last 23 bits)
for(i = 6; i >= 0; i--) // the most significant 7 bits of mantissa
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{cout << '1';}
else {cout << '0';} // 0 bit
}
while (--j >= 0) // last (least significant) 2 bytes of `f' (1, 0)
{ // the rest of mantissa (16 bits)
val = cp[j];
for(i = 7; i >= 0; i--)
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{cout << '1';}
else {cout << '0';} // 0 bit
}
}
cout << endl;
}
void printDoubleBinary(double d) // Display a double in binary
{ // we assume `double' has 64 bits: 1 for sign, 11 for exp, 52 for mantissa
int i = 7; // first (most significant) position in a byte
int j = sizeof(double)-1; // first (most significant) byte (7) of a double
unsigned char* cp = reinterpret_cast<unsigned char*>(&d); // we assume sizeof(char) = 1
unsigned char val = cp[j]; // most significant byte of `d'
// first print the sign (bit 63):
if(val & (1 << i)) // set (1) bit for negative numbers
{cout << '1';}
else {cout << '0';} // 0 bit for positive numbers
cout << ' '; // separate the sign from the rest of `d' in binary
for(i = 6; i >= 0; i--) // the most significant 7 bits of the exponent
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{cout << '1';}
else {cout << '0';} // 0 bit
}
j--; // move to the next (less significant) byte of `d' (6)
val = cp[j];
for(i = 7; i >= 4; i--) // the least significant 4 bits of the exponent
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{cout << '1';}
else {cout << '0';} // 0 bit
}
cout << ' '; // separate exponent from mantissa (last 52 bits)
for(; i >= 0; i--) // the most significant 4 bits of mantissa (3, 2, 1, 0)
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{cout << '1';}
else {cout << '0';} // 0 bit
}
while (--j >= 0) // last (least significant) 6 bytes of `d' (5, 4, ..., 0)
{ // the rest of mantissa (48 bits)
val = cp[j];
for(i = 7; i >= 0; i--)
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{cout << '1';}
else {cout << '0';} // 0 bit
}
}
cout << endl;
}
void printLongDoubleBinary(long double ld) // Display a long double in binary
{ // extended precision, 80 bits: 1 sign, 15 exp, 1 int part, 63 fraction
int i; // count bits of a byte
int j = sizeof(long double)-1; // first byte (15) of a long double
unsigned char* cp = reinterpret_cast<unsigned char*>(&ld); // we assume sizeof(char) = 1
unsigned char val; // for the bytes of `ld'
for(; j >=10; j--) // first 6 bytes are garbage (48 bits)
{ // we assume sizeof(long double) = 16 (128 = 48 + 80 bits)
val = cp[j];
for(i = 7; i >= 0; i--)
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{cout << '1';}
else {cout << '0';} // 0 bit
}
}
cout << ' '; // separate garbage (48 bits) from the rest (80 bits)
val = cp[j]; // byte 9 of `ld' (the most significant of the last 10 bytes)
i = 7; // first (most significant) position in a byte
// first print the sign (bit 79):
if(val & (1 << i)) // set (1) bit for negative numbers
{cout << '1';}
else {cout << '0';} // 0 bit for positive numbers
cout << ' '; // separate the sign from the rest of `ld' in binary
for(i = 6; i >= 0; i--) // the most significant 7 bits of the exponent
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{cout << '1';}
else {cout << '0';} // 0 bit
}
j--; // move to the next (less significant) byte of `ld' (8)
val = cp[j];
for(i = 7; i >= 0; i--) // the least significant 8 bits of the exponent
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{cout << '1';}
else {cout << '0';} // 0 bit
}
cout << endl; // separate exponent from mantissa (last 64 bits)
j--; // move to the next (less significant) byte of `ld' (7)
val = cp[j];
i = 7;
// print the integer part of mantissa (bit 63):
if(val & (1 << i)) // set (1) bit
{cout << '1';}
else {cout << '0';} // 0 bit
cout << ' '; // separate integer part from fraction (63 bits)
i = 6;
// print the first (most significant) bit of the fraction (bit 62):
if(val & (1 << i)) // set (1) bit
{cout << '1';}
else {cout << '0';} // 0 bit
cout << ' '; // separate first bit from the rest of the fraction (62 bits)
for(i = 5; i >= 0; i--) // next most significant 6 bits of the fraction
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{cout << '1';}
else {cout << '0';} // 0 bit
}
while (--j >= 0) // last (least significant) 7 bytes of `ld' (6, 5, ..., 0)
{ // the rest of the fraction and of mantissa (56 bits)
val = cp[j];
for(i = 7; i >= 0; i--)
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{cout << '1';}
else {cout << '0';} // 0 bit
}
}
cout << endl;
}
/*
g++ FloatBinary2.cpp -o FloatBinary2
./FloatBinary2
Must provide a number
./FloatBinary2 0 1
Must provide a number // exactly one number
./FloatBinary2 0
0 00000000 00000000000000000000000 // single-precision floating-point
0 00000000000 0000000000000000000000000000000000000000000000000000 // double
000000000000000000000000000000000000000000000000 0 000000000000000 // long
0 0 00000000000000000000000000000000000000000000000000000000000000 // double
./FloatBinary2 1
0 01111111 00000000000000000000000
0 01111111111 0000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000 0 011111111111111
1 0 00000000000000000000000000000000000000000000000000000000000000
./FloatBinary2 2
0 10000000 00000000000000000000000
0 10000000000 0000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000 0 100000000000000
1 0 00000000000000000000000000000000000000000000000000000000000000
./FloatBinary2 3
0 10000000 10000000000000000000000
0 10000000000 1000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000 0 100000000000000
1 1 00000000000000000000000000000000000000000000000000000000000000
./FloatBinary2 4
0 10000001 00000000000000000000000
0 10000000001 0000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000 0 100000000000001
1 0 00000000000000000000000000000000000000000000000000000000000000
./FloatBinary2 0.1
0 01111011 10011001100110011001101
0 01111111011 1001100110011001100110011001100110011001100110011010
000000000000000000000000000000000000000000000000 0 011111111111011
1 1 00110011001100110011001100110011001100110011001101000000000000
./FloatBinary 0.2
0 01111100 10011001100110011001101
0 01111111100 1001100110011001100110011001100110011001100110011010
000000000000000000000000000000000000000000000000 0 011111111111100
1 1 00110011001100110011001100110011001100110011001101000000000000
./FloatBinary2 -0.1
1 01111011 10011001100110011001101
1 01111111011 1001100110011001100110011001100110011001100110011010
000000000000000000000000000000000000000000000000 1 011111111111011
1 1 00110011001100110011001100110011001100110011001101000000000000
./FloatBinary2 -.2
1 01111100 10011001100110011001101
1 01111111100 1001100110011001100110011001100110011001100110011010
000000000000000000000000000000000000000000000000 1 011111111111100
1 1 00110011001100110011001100110011001100110011001101000000000000
./FloatBinary2 15
0 10000010 11100000000000000000000
0 10000000010 1110000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000 0 100000000000010
1 1 11000000000000000000000000000000000000000000000000000000000000
./FloatBinary2 15.1
0 10000010 11100011001100110011010
0 10000000010 1110001100110011001100110011001100110011001100110011
000000000000000000000000000000000000000000000000 0 100000000000010
1 1 11000110011001100110011001100110011001100110011001100000000000
./FloatBinary2 15.2
0 10000010 11100110011001100110011
0 10000000010 1110011001100110011001100110011001100110011001100110
000000000000000000000000000000000000000000000000 0 100000000000010
1 1 11001100110011001100110011001100110011001100110011000000000000
./FloatBinary 15.3
0 10000010 11101001100110011001101
0 10000000010 1110100110011001100110011001100110011001100110011010
000000000000000000000000000000000000000000000000 0 100000000000010
1 1 11010011001100110011001100110011001100110011001101000000000000
*/
Chapter_3 Exercise_3-28 | BACK_TO_TOP | PointerIncrement Exercise_3-30 |
Comments
Post a Comment