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 | */ |