/* float.c * * Examine floating point numbers * */ #include #include typedef union { float v; long iv; } NUMBER; void from_number(NUMBER f, int *sign, int *exponent, long *matissa); float to_number(int sign, int exponent, long mantissa); void print_number(NUMBER f); int main() { int i; int sign, exponent; long mantissa; double error; NUMBER f, g; for (i=0; i<=32; i++) { printf("number %2d: ",i); f.v = i; print_number(f); from_number(f,&sign,&exponent,&mantissa); g.v = to_number(sign,exponent,mantissa); if (f.v!=g.v) printf("*** conversion failed ***\n"); } printf("\n\n"); printf("number 1/2: "); f.v = 0.5; print_number(f); printf("number 1/4: "); f.v = 0.25; print_number(f); printf("number 1/10: "); f.v = 0.10; print_number(f); printf("FLT_EPSILON "); f.v = to_number(0,127,1L)-to_number(0,127,0L); print_number(f); printf("\n\n"); f.v = 0.0; g.v = 0.1; for (i=0; i<10; i++) f.v += g.v; error = fabs(f.v-1.0); printf("0.1 added 10 times: error (%8.2e) ",error); print_number(f); f.v = 0.0; g.v = 0.01; for (i=0; i<100; i++) f.v += g.v; error = fabs(f.v-1.0); printf("0.01 added 100 times: error (%8.2e) ",error); print_number(f); f.v = 0.0; g.v = 0.001; for (i=0; i<1000; i++) f.v += g.v; error = fabs(f.v-1.0); printf("0.001 added 1,000 times: error (%8.2e) ",error); print_number(f); f.v = 0.0; g.v = 0.0001; for (i=0; i<10000; i++) f.v += g.v; error = fabs(f.v-1.0); printf("0.0001 added 10,000 times: error (%8.2e) ",error); print_number(f); printf("\n\n"); for (i=0; i<4; i++) { f.v = to_number(0,i,0L); print_number(f); } printf("\n\n"); f.v = to_number(0,0xff,0L); print_number(f); for (i=0; i<4; i++) { f.v = to_number(0,0xff-i,0x7fffff); print_number(f); } return 0; } void print_number(NUMBER f) { int sign, exponent; long mantissa; sign = (f.iv>>31); exponent = (f.iv>>23)&0xff; mantissa = (f.iv)&0x7fffff; printf("%d %2x %6lx %20.14g\n",sign,exponent,mantissa,f.v); } void from_number(NUMBER f, int *sign, int *exponent, long *mantissa) { *sign = (f.iv>>31); *exponent = (f.iv>>23)&0xff; *mantissa = (f.iv)&0x7fffff; } float to_number(int sign, int exponent, long mantissa) { NUMBER f; f.iv = ((sign&1)<<8) | (exponent&0xff); f.iv = (f.iv<<23) | (mantissa&0x7fffff); return f.v; }