Created
May 14, 2017 04:55
-
-
Save kccqzy/7cb19493c0175ac890c7848136c8ccae to your computer and use it in GitHub Desktop.
Explain an IEEE754 single-/double-precision floating point number
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <bitset> | |
#include <iomanip> | |
#include <iostream> | |
#include <string.h> | |
namespace { | |
template <typename Floating, typename Integral, int expBits> | |
void explain(Floating x) { | |
static_assert(sizeof(Floating) == sizeof(Integral), | |
"types not the same size"); | |
Integral l; | |
memcpy(&l, &x, sizeof l); | |
int constexpr totalBits = 8 * sizeof l; | |
int constexpr fracBits = totalBits - 1 - expBits; | |
Integral sign = l >> (totalBits - 1); | |
Integral exp = (l >> fracBits) & (((Integral) 1 << expBits) - 1); | |
Integral frac = l & (((Integral) 1 << fracBits) - 1); | |
bool is_normal = exp; | |
Integral bias = ((Integral) 1 << (expBits - 1)) - 1; | |
Integral actual_exp = is_normal ? exp - bias : 1 - bias; | |
std::cout << "Number: " << std::setprecision(30) << x << '\n' | |
<< " " << std::hexfloat << x << std::defaultfloat << '\n' | |
<< "Sign bit: " << std::bitset<1>(sign) << '\n' | |
<< "Exp bits: " << std::bitset<expBits>(exp) << '\n' | |
<< "Frac bits: " << std::bitset<fracBits>(frac) << '\n'; | |
if (exp != ((Integral) 1 << expBits) - 1) | |
std::cout << "Actual exponent: " << actual_exp << '\n' | |
<< "Mathematical value: " << (sign ? "-" : "") << "2^(" | |
<< actual_exp << ") * (" << (int) is_normal << " + " << frac << " / 2^" << fracBits << ")\n\n"; | |
else std::cout << "\n"; | |
} | |
} | |
void explain_double(double x) { | |
explain<double, long, 11>(x); | |
} | |
void explain_float(float x) { | |
explain<float, int, 8>(x); | |
} | |
int main(void) { | |
for (int i = 0; i < 20; ++i) { | |
explain_float((float) i / 10.0f); | |
explain_double(i / 10.0); | |
} | |
explain_double(4.9406564584124654418e-324); // Smallest (positive) denormal | |
explain_double(2.2250738585072008890e-308); // Biggest denormal | |
explain_double(2.2250738585072013831e-308); // Smallest (positive) normal | |
explain_double(1.7976931348623157081e+308); // Biggest normal | |
explain_double(1.0 / 0.0); | |
explain_double(0.0 / 0.0); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment