/* Display structure of floating-point numbers */ #include #include float strtof(const char* nptr, char** endptr); #define FLOAT_SIZE 32 #define FRAC_SIZE 23 #define EXP_SIZE 8 #define BIAS ((1 << (EXP_SIZE - 1)) - 1) #define FRAC_MASK ((1 << FRAC_SIZE) - 1) #define EXP_MASK ((1 << EXP_SIZE) - 1) /* Floating point helpers */ unsigned f2u(float f) { union { unsigned u; float f; } v; v.u = 0; v.f = f; return v.u; } static float u2f(unsigned u) { union { unsigned u; float f; } v; v.u = u; return v.f; } /* Get exponent */ unsigned get_exp(unsigned uf) { return (uf >> FRAC_SIZE) & EXP_MASK; } /* Get fraction */ unsigned get_frac(unsigned uf) { return uf & FRAC_MASK; } /* Get sign */ unsigned get_sign(unsigned uf) { return (uf >> (FLOAT_SIZE - 1)) & 0x1; } void show_float(unsigned uf) { float f = u2f(uf); unsigned exp = get_exp(uf); unsigned frac = get_frac(uf); unsigned sign = get_sign(uf); printf("\nFloating point value %.10g\n", f); printf("Bit Representation 0x%.8x, sign = %x, exponent = 0x%.2x, fraction = 0x%.6x\n", uf, sign, exp, frac); if (exp == EXP_MASK) { if (frac == 0) { printf("%cInfinity\n", sign ? '-' : '+'); } else printf("Not-A-Number\n"); } else { int denorm = (exp == 0); int uexp = denorm ? 1 - BIAS : exp - BIAS; int mantissa = denorm ? frac : frac + (1 << FRAC_SIZE); float fman = (float)mantissa / (float)(1 << FRAC_SIZE); printf("%s. %c%.10f X 2^(%d)\n", denorm ? "Denormalized" : "Normalized", sign ? '-' : '+', fman, uexp); } } /* Extract hex/decimal/or float value from string */ static int get_num_val(char* sval, unsigned* valp) { char* endp; /* See if it's an integer or floating point */ int ishex = 0; int isfloat = 0; int i; for (i = 0; sval[i]; i++) { switch (sval[i]) { case 'x': case 'X': ishex = 1; break; case 'e': case 'E': if (!ishex) isfloat = 1; break; case '.': isfloat = 1; break; default: break; } } if (isfloat) { float fval = strtof(sval, &endp); if (!*endp) { *valp = *(unsigned*)&fval; return 1; } return 0; } else { long long int llval = strtoll(sval, &endp, 0); long long int upperbits = llval >> 31; /* will give -1 for negative, 0 or 1 for positive */ if (valp && (upperbits == 0 || upperbits == -1 || upperbits == 1)) { *valp = (unsigned)llval; return 1; } return 0; } } void usage(char* fname) { printf("Usage: %s val1 val2 ...\n", fname); printf("Values may be given as hex patterns or as floating point numbers\n"); exit(0); } int main(int argc, char* argv[]) { int i; unsigned uf; if (argc < 2) usage(argv[0]); for (i = 1; i < argc; i++) { char* sval = argv[i]; if (get_num_val(sval, &uf)) { show_float(uf); } else { printf("Invalid 32-bit number: '%s'\n", sval); usage(argv[0]); } } return 0; }