View difference between Paste ID: 6UVTi55d and VTshBG4i
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
*/