#include <inttypes.h>
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
/* Interpret a string containing a numeral for an integer value as an encoding
of an IEEE-754 basic 32-bit binary floating-point value.
*/
static float Interpret(const char *s)
{
// Interpret the string as an integer numeral. Errors are not handled.
uint32_t x = strtoumax(s, NULL, 16);
// Separate the sign (1 bit), exponent (8), and significand (23) fields.
uint32_t sign = x>>31;
uint32_t exponent = (x>>23) & 0xff;
uint32_t significand = x & 0x7fffff;
// Interpret the sign field.
float Sign = sign ? -1 : +1;
// Create an object to hold the magnitude (or NaN).
float Magnitude;
// How we form the magnitude depends on the exponent field.
switch (exponent)
{
// If the exponent field is zero, the number is zero or subnormal.
case 0:
{
// In a zero or subnormal number, the significand starts with 0.
float Significand = 0 + significand * 0x1p-23f;
// In a zero or subnormal number, the exponent has its minimum value.
int Exponent = 1 - 127;
// Form the magnitude from the significand and exponent.
Magnitude = ldexpf(Significand, Exponent);
break;
}
// If the exponent field is all ones, the datum is infinity or a NaN.
case 0x7fffff:
{
/* If the significand field is zero, the datum is infinity.
Otherwise it is a NaN. Note that different NaN payloads and
types (quiet or signaling) are not supported here. Standard C
does not provide good support for these.
*/
Magnitude = significand == 0 ? INFINITY : NAN;
break;
}
// Otherwise, the number is normal.
default:
{
// In a normal number, the significand starts with 1.
float Significand = 1 + significand * 0x1p-23f;
// In a normal number, the exponent is biased by 127.
int Exponent = (int) exponent - 127;
// Form the magnitude from the significand and exponent.
Magnitude = ldexpf(Significand, Exponent);
}
}
// Combine the sign and magnitude and return the result.
return copysignf(Magnitude, Sign);
}
int main(void)
{
printf("%.99g\n", Interpret("0x466F9100"));
}