SHOW:
|
|
- or go back to the newest paste.
1 | //Do note that much greater precision can be achieved if a long double is used instead. | |
2 | //A long double version of log(), floor(), and pow() would need to be used, though. | |
3 | ||
4 | #include<stdio.h> | |
5 | #include <math.h> | |
6 | - | #define abs(a) ((a)<0?-(a):(a)) |
6 | + | |
7 | void store_float(FILE* f, double value, int bytes){ | |
8 | bytes--; | |
9 | int is_negative = value >= 0 ? 0 : 1; | |
10 | if( value < 0 ) | |
11 | value = -value; | |
12 | int power = floor(bytes*8-log(value)/log(2)); | |
13 | if( power < -64 || power >= 64 || isinf(value) || isnan(value) ) | |
14 | - | value = abs( value ); |
14 | + | |
15 | ||
16 | value *= pow( 2, power ); | |
17 | value = floor( value ); | |
18 | power = (power + 64) & 0xFF; | |
19 | power |= is_negative << 7; | |
20 | fputc( power, f ); | |
21 | while( value > 0 && bytes > 0 ){ | |
22 | fputc( value-floor(value/256)*256, f ); | |
23 | value = floor( value/256 ); | |
24 | bytes--; | |
25 | } | |
26 | } | |
27 | ||
28 | double read_float( FILE *f, int bytes ){ | |
29 | bytes--; | |
30 | int power = fgetc( f ); | |
31 | int is_negative = power & 0x80; | |
32 | power &= 0x7F; | |
33 | power -= 64; | |
34 | double value = 0; | |
35 | double multiplier = 1; | |
36 | while( bytes-- > 0 ){ | |
37 | value += (double)fgetc( f ) * multiplier; | |
38 | multiplier *= 256; | |
39 | } | |
40 | if( is_negative ) | |
41 | value *= -1; | |
42 | value /= pow( 2, power ); | |
43 | if( power == 63 ) | |
44 | value = pow(2, 1024); | |
45 | return value; | |
46 | } | |
47 | ||
48 | int main(){ | |
49 | FILE *f = fopen( "test.bin", "w" ); | |
50 | ||
51 | store_float( f, 1080.746356, 8 ); | |
52 | store_float( f, 1080.746356, 4 ); | |
53 | store_float( f, 1080.746356, 2 ); | |
54 | store_float( f, 1234567890123456789.123456789, 8 ); | |
55 | store_float( f, 1234567890123456789.123456789, 4 ); | |
56 | store_float( f, 1234567890123456789.123456789, 2 ); | |
57 | store_float( f, pow(2,1024), 2 ); | |
58 | ||
59 | fclose(f); | |
60 | ||
61 | ||
62 | f = fopen( "test.bin", "r" ); | |
63 | ||
64 | printf("%f\n", read_float( f, 8 )); | |
65 | printf("%f\n", read_float( f, 4 )); | |
66 | printf("%f\n", read_float( f, 2 )); | |
67 | printf("%f\n", read_float( f, 8 )); | |
68 | printf("%f\n", read_float( f, 4 )); | |
69 | printf("%f\n", read_float( f, 2 )); | |
70 | printf("%f\n", read_float( f, 2 )); | |
71 | ||
72 | fclose(f); | |
73 | ||
74 | } | |
75 | ||
76 | ||
77 | /* Output: | |
78 | ||
79 | 1080.746356 | |
80 | 1080.746338 | |
81 | 1080.000000 | |
82 | 1234567890123456800.000000 | |
83 | 1234567802111655900.000000 | |
84 | 1233986297899515900.000000 | |
85 | 1.#INF00 | |
86 | ||
87 | ||
88 | ||
89 | Contents of test.bin (hex dump, separated by stored value): | |
90 | 6D 90 65 FA 25 E2 17 87 | |
91 | 4D E2 17 87 | |
92 | 3D 87 | |
93 | 3B 08 4C EF A3 87 10 89 | |
94 | 1B 87 10 89 | |
95 | 0B 89 | |
96 | 7F 00 | |
97 | */ |