Skip to content

Instantly share code, notes, and snippets.

@kccqzy
Created May 14, 2017 04:55
Show Gist options
  • Save kccqzy/7cb19493c0175ac890c7848136c8ccae to your computer and use it in GitHub Desktop.
Save kccqzy/7cb19493c0175ac890c7848136c8ccae to your computer and use it in GitHub Desktop.
Explain an IEEE754 single-/double-precision floating point number
#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