diff options
author | Mike Buland <eichlan@xagasoft.com> | 2011-03-08 08:06:44 +0000 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2011-03-08 08:06:44 +0000 |
commit | 8f53239f4ceccfd747283c8f0d7968fa40731faf (patch) | |
tree | 4a3fd32ee9f715cc224720b387aa5dd1512f3802 /src/tools/float.cpp | |
parent | b8eaef64b48170467ee38b8399a951b967f468e6 (diff) | |
download | libbu++-8f53239f4ceccfd747283c8f0d7968fa40731faf.tar.gz libbu++-8f53239f4ceccfd747283c8f0d7968fa40731faf.tar.bz2 libbu++-8f53239f4ceccfd747283c8f0d7968fa40731faf.tar.xz libbu++-8f53239f4ceccfd747283c8f0d7968fa40731faf.zip |
sigh, another program that's not realy a tool, it was the easiest place for it
I should add a new class of program to libbu++ or clear out most of my old tests
or something. Anyway, almost fully C99 compliant float to normalized hex string
and back functions in pure math. Really slick, really portable. they don't
handle +/-NaN, +/-Inf, or the special alternate format for subnormal numbers,
try entering a 0.0...01 where I cut out about 200 zeros, you'll see what I mean.
Diffstat (limited to '')
-rw-r--r-- | src/tools/float.cpp | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/src/tools/float.cpp b/src/tools/float.cpp new file mode 100644 index 0000000..2c241f3 --- /dev/null +++ b/src/tools/float.cpp | |||
@@ -0,0 +1,130 @@ | |||
1 | #include <bu/sio.h> | ||
2 | #include <bu/string.h> | ||
3 | #include <stdlib.h> | ||
4 | #include <math.h> | ||
5 | |||
6 | using namespace Bu; | ||
7 | |||
8 | Bu::String ftos( double dNum ) | ||
9 | { | ||
10 | if( dNum == 1.0 ) | ||
11 | return "0x1p+0"; | ||
12 | if( dNum == 0.0 ) | ||
13 | return signbit(dNum)?"-0x0p+0":"0x0p+0"; | ||
14 | if( dNum == -1.0 ) | ||
15 | return "-0x1p+0"; | ||
16 | Bu::String s("0x1."); | ||
17 | if( signbit(dNum) ) | ||
18 | { | ||
19 | s.prepend("-"); | ||
20 | dNum = -dNum; | ||
21 | } | ||
22 | /* | ||
23 | for( int j = 0; j < 150 && dNum; j++ ) | ||
24 | { | ||
25 | dNum = dNum*2; | ||
26 | sio << dNum << " -- " << (int)dNum << sio.nl; | ||
27 | if( (int)dNum == 0 ) | ||
28 | s += '0'; | ||
29 | else | ||
30 | { | ||
31 | s += '1'; | ||
32 | dNum -= 1.0; | ||
33 | } | ||
34 | } | ||
35 | return s; | ||
36 | */ | ||
37 | int iPower = 0; | ||
38 | if( dNum < 1.0 ) | ||
39 | { | ||
40 | while( dNum < 1.0 ) | ||
41 | { | ||
42 | dNum *= 2.0; | ||
43 | iPower--; | ||
44 | } | ||
45 | } | ||
46 | else if( dNum >= 2.0 ) | ||
47 | { | ||
48 | while( dNum >= 2.0 ) | ||
49 | { | ||
50 | dNum *= 0.5; | ||
51 | iPower++; | ||
52 | } | ||
53 | } | ||
54 | dNum -= (int)dNum; | ||
55 | for( int j = 0; j < 150 && dNum; j++ ) | ||
56 | { | ||
57 | dNum = dNum*16.0; | ||
58 | s += "0123456789abcdef"[(int)dNum]; | ||
59 | dNum -= (int)dNum; | ||
60 | } | ||
61 | s.formatAppend("p%+d", iPower ); | ||
62 | return s; | ||
63 | } | ||
64 | |||
65 | double stof( const Bu::String &s ) | ||
66 | { | ||
67 | if( s == "0x1p+0" ) | ||
68 | return 1.0; | ||
69 | if( s == "-0x1p+0" ) | ||
70 | return -1.0; | ||
71 | if( s == "0x0p+0" ) | ||
72 | return 0.0; | ||
73 | if( s == "-0x0p+0" ) | ||
74 | return 0.0; | ||
75 | double dNum = 0.0; | ||
76 | int iPPos = s.getSize()-1; | ||
77 | for(; s[iPPos] != 'p'; iPPos--) { } | ||
78 | for( int i = iPPos-1; s[i] != '.'; i-- ) | ||
79 | { | ||
80 | if( s[i]>='0' && s[i]<='9' ) | ||
81 | { | ||
82 | dNum += s[i]-'0'; | ||
83 | } | ||
84 | else if( s[i]>='a' && s[i]<='f' ) | ||
85 | { | ||
86 | dNum += s[i]-'a'+10.0; | ||
87 | } | ||
88 | dNum *= 0.0625; | ||
89 | } | ||
90 | |||
91 | dNum += 1.0; | ||
92 | |||
93 | int iTop = strtol( s.getStr()+iPPos+1, NULL, 10 ); | ||
94 | if( iTop < 0 ) | ||
95 | { | ||
96 | for( int j = 0; j > iTop; j-- ) | ||
97 | { | ||
98 | dNum *= 0.5; | ||
99 | } | ||
100 | } | ||
101 | else | ||
102 | { | ||
103 | for( int j = 0; j < iTop; j++ ) | ||
104 | { | ||
105 | dNum *= 2.0; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | if( s[0] == '-' ) | ||
110 | return -dNum; | ||
111 | return dNum; | ||
112 | } | ||
113 | |||
114 | int main( int argc, char *argv[] ) | ||
115 | { | ||
116 | for( int j = 1; j < argc; j++ ) | ||
117 | { | ||
118 | double dNum = strtod( argv[j], NULL ); | ||
119 | |||
120 | String s = ftos( dNum ); | ||
121 | sio << "in: " << dNum << sio.nl; | ||
122 | sio << "mine: " << s << sio.nl; | ||
123 | printf("printf: %a\n", dNum ); | ||
124 | sio << "out: " << stof( s ) << sio.nl; | ||
125 | sio << "match: " << (stof( s ) == dNum) << sio.nl << sio.nl; | ||
126 | } | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||