/** * ieee.c * A library of functions for exploring IEEE floating point numbers. */ // +---------+-------------------------------------------------------- // | Headers | // +---------+ #include #include // For pow #include "ieee.h" #include "bit-utils.h" // +---------+-------------------------------------------------------- // | Helpers | // +---------+ /** * Get the bits for the significand. */ int ieee32_significand_bits (float f) { return f2i (f) & 0x7FFFFF; // That's 0000000 01111111 11111111 11111111 } // ieee32_significand_bits // +--------------------+--------------------------------------------- // | Exported Functions | // +--------------------+ int ieee32_sign (float f) { return ith_bit (f2i (f), 31); } // ieee32_sign int ieee32_exponent (float f) { int exponent; exponent = f2i (f); // Drop the left bit exponent = zero_bit (exponent, 31); // Shift bits over so that they're in the convenient place exponent = exponent >> 23; // Subtract the bias exponent = exponent - 127; // And we're done return exponent; } // ieee32_exponent float ieee32_significand (float f, int hidden) { int bits = ieee32_significand_bits (f); // Bits of significand float result = (float) hidden; // Result we're computing int i; // The bit we're looking at float value = 0.5; // The value of that bit. for (i = 22; i >= 0; i--) { // If the bit is set, add its value if (ith_bit (bits, i)) result += value; // Move to the next value value /= 2.0; } // for // And we're done return result; } // ieee32_significand float ieee32_significand_hack (float f, int hidden) { int bits = ieee32_significand_bits (f); if (hidden) bits = bits | 1 << 23; return bits / pow (2, 23); } // ieee32_significand_hack void describe_float (float f) { int sign; // The sign of the number int exponent; // The exponent of the number float significand; // The significand int small; // Special case: Really small numbers // Print it printf ("Exploring floating point number %f:\n", f); // Get the sign sign = ieee32_sign (f); // Get the exponent exponent = ieee32_exponent (f); // Handle special values if (exponent == 128) { // Infinities if (ieee32_significand_bits (f) == 0) { if (sign) printf (" Negative infinity\n"); else printf (" Positive infinity\n"); } // infinite else printf ("Not a number\n"); return; } // special values // Determine if it's small small = exponent == -127; // Get the significand significand = ieee32_significand (f, !small); // Special case: Small numbers if (exponent == -127) exponent = -126; printf (" Sign: %s\n", sign ? "-" : "+"); printf (" Exponent: %d\n", exponent); printf (" Significand: %f\n", significand); printf (" Significand2: %f\n", ieee32_significand_hack (f, !small)); } // describe_float