char ieeefloat_c_rcs_id[] = "$Id: ieeefloat.c,v 1.4 2003-07-17 10:36:49 hjp Exp $"; /* ieeefloat: print binary representations of IEEE 754 FP numbers. * * $Log: ieeefloat.c,v $ * Revision 1.4 2003-07-17 10:36:49 hjp * Added * Added dependency to force .c -> .o compilation. * * Revision 1.3 2002/03/18 20:41:09 hjp * Added format specifiers * * Revision 1.2 2000/02/08 17:04:37 hjp * Added -f and -d options to force input to be float or double format. * * Revision 1.1 1998/03/20 20:09:53 hjp * Initial release: * prints arguments as strings, floats, and doubles decimal and binary. * */ #include #include #include #include #include #define BITS_FLT 32 #define EXC_FLT 127 #define MANT_FLT 23 #define SIGN_FLT ((floatint)1<<(BITS_FLT-1)) #define BITS_DBL 64 #define EXC_DBL 1023 #define MANT_DBL 52 #define SIGN_DBL ((doubleint)1<<(BITS_DBL-1)) #if ULONG_MAX/2+1 == (1UL << (BITS_FLT-1)) typedef unsigned long int floatint; #elif UINT_MAX/2+1 == (1U << (BITS_FLT-1)) typedef unsigned int floatint; #else #error "no integral type with BITS_FLT bits" #endif #if ULONG_MAX/2+1 == (1UL << (BITS_DBL-1)) typedef unsigned long int doubleint; #else /* We cannot portably test for the existance of long long. * If it doesn't exist, either the compiler or sanitychecks * will complain */ typedef unsigned long long int doubleint; #endif char *cmnd; char *floatformat = "%24.7g"; char *doubleformat = "%24.17g"; static void usage(void) { fprintf(stderr, "Usage: %s [-f|-d] [-F format] [-D format] fp-number ...\n", cmnd); exit(1); } static void printbinary (doubleint b, int d) { while (--d >= 0) { putchar('0' + ((b >> d) & 1)); } } static void printfloat(float f) { union { floatint i; float f; } u; floatint e; floatint m; u.f = f; printf(floatformat, f); printf(": "); printf("%c ", (u.i & SIGN_FLT) ? '-' : '+'); u.i &= ~SIGN_FLT; e = u.i >> MANT_FLT; printf(" "); printbinary(e, BITS_FLT-1-MANT_FLT); m = (u.i & (((floatint)1 << MANT_FLT) - 1)); if (e == 0) { /* denormalized */ printf(" [0.]"); } else { printf(" [1.]"); } printbinary(m, MANT_FLT); printf("\n"); } static void printdouble(double f) { union { doubleint i; double f; } u; doubleint e; doubleint m; u.f = f; printf(doubleformat, f); printf(": "); printf("%c ", (u.i & SIGN_DBL) ? '-' : '+'); u.i &= ~SIGN_DBL; e = u.i >> MANT_DBL; printbinary(e, BITS_DBL-1-MANT_DBL); m = (u.i & (((doubleint)1 << MANT_DBL) - 1)); if (e == 0) { printf(" [0.]"); } else { printf(" [1.]"); } printbinary(m, MANT_DBL); printf("\n"); } static void sanitychecks(void) { union { floatint i; float f; } fu; union { doubleint i; double f; } du; /* size */ assert (sizeof(floatint) == sizeof(float)); assert (sizeof(doubleint) == sizeof(double)); /* some numbers */ fu.f = 0; assert (fu.i == 0); du.f = 0; assert (du.i == 0); fu.f = 1.0; assert (fu.i == (floatint)(0 + EXC_FLT) << MANT_FLT); du.f = 1.0; assert (du.i == (doubleint)(0 + EXC_DBL) << MANT_DBL); fu.f = 1.5; assert (fu.i == (((floatint)(0 + EXC_FLT) << MANT_FLT) | (1 << (MANT_FLT-1)))); du.f = 1.5; assert (du.i == (((doubleint)(0 + EXC_DBL) << MANT_DBL) | ((doubleint)1 << (MANT_DBL-1)))); } int main(int argc, char**argv) { int i; int convfloat = 0; char *p; cmnd = argv[0]; sanitychecks(); for (i = 1; i < argc; i++) { double d; if (strcmp(argv[i], "-f") == 0) { convfloat = 1; continue; } else if (strcmp(argv[i], "-d") == 0) { convfloat = 0; continue; } else if (strcmp(argv[i], "-F") == 0) { if (!argv[i+1]) usage(); floatformat = argv[i+1]; i++; continue; } else if (strcmp(argv[i], "-D") == 0) { if (!argv[i+1]) usage(); doubleformat = argv[i+1]; i++; continue; } d = strtod(argv[i], &p); if (p && *p) usage(); if (convfloat) { d = (float) d; } printf("%s\n", argv[i]); printdouble(d); printfloat(d); } return 0; }