-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprint-fp.cpp
More file actions
74 lines (53 loc) · 1.47 KB
/
print-fp.cpp
File metadata and controls
74 lines (53 loc) · 1.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/*
Print-format a 32-bit float by exploiting exponent
Blog post: http://alexpolt.github.io/print-fp.html
Alexandr Poltavsky
*/
#include <cstdio>
#include <cmath>
void print_fp( float number, int digits_count ) {
union {
float d;
int u;
};
d = number;
//deal with sign
bool minus = u >> 31;
u = u & ~(1 << 31);
//calculate base-10 exponent
double exp = (u >> 23) - 127;
double exp10 = exp / log2( 10.0 );
//adjust the number
u = (u & ~(0xFF << 23)) | (127 << 23);
double d2 = double(d) * pow( 10.0, exp10 - int(exp10) );
if( d2 >= 10.0 ) { d2 = d2 / 10.0; exp10+=1.0; }
if( d2 < 1.0 ) { d2 = d2 * 10.0; exp10-=1.0; }
static char digits[] = "0123456789";
//print sign
if( minus ) putc( '-', stdout );
//print integer part
int i = int( d2 );
putc( digits[i], stdout );
putc( '.', stdout );
d2 = d2 - i;
//print fractional part
while( digits_count-- ) {
d2 = d2 * 10.0;
int i = int( d2 );
putc( digits[i], stdout );
d2 = d2 - i;
}
//print exponent part
printf("e%d\n", int(exp10));
}
int main() {
double d;
//the two doubles below are special, in that a float can't distinguish between them
//taken from Bruce Dawson post "Float Precision–From Zero to 100+ Digits"
d = 8.589973e9;
printf("%.10f\n", d);
print_fp( d , 10 );
d = 8.589974e9;
printf("%.10f\n", d);
print_fp( d , 10 );
}