22
22
23
23
*/
24
24
25
- #include < stdio.h>
26
25
#include < stdlib.h>
27
26
#include < string.h>
28
27
#include < stdbool.h>
29
28
#include < stdint.h>
30
29
#include < math.h>
30
+ #include < limits>
31
31
#include " stdlib_noniso.h"
32
32
33
33
extern " C" {
@@ -41,9 +41,79 @@ char* ultoa(unsigned long value, char* result, int base) {
41
41
}
42
42
43
43
char * dtostrf (double number, signed char width, unsigned char prec, char *s) {
44
- char fmt[32 ];
45
- sprintf (fmt, " %%%d.%df" , width, prec);
46
- sprintf (s, fmt, number);
44
+ bool negative = false ;
45
+
46
+ if (isnan (number)) {
47
+ strcpy (s, " nan" );
48
+ return s;
49
+ }
50
+ if (isinf (number)) {
51
+ strcpy (s, " inf" );
52
+ return s;
53
+ }
54
+
55
+ char * out = s;
56
+
57
+ int fillme = width; // how many cells to fill for the integer part
58
+ if (prec > 0 ) {
59
+ fillme -= (prec+1 );
60
+ }
61
+
62
+ // Handle negative numbers
63
+ if (number < 0.0 ) {
64
+ negative = true ;
65
+ fillme--;
66
+ number = -number;
67
+ }
68
+
69
+ // Round correctly so that print(1.999, 2) prints as "2.00"
70
+ // I optimized out most of the divisions
71
+ double rounding = 2.0 ;
72
+ for (uint8_t i = 0 ; i < prec; ++i)
73
+ rounding *= 10.0 ;
74
+ rounding = 1.0 / rounding;
75
+
76
+ number += rounding;
77
+
78
+ // Figure out how big our number really is
79
+ double tenpow = 1.0 ;
80
+ int digitcount = 1 ;
81
+ double nextpow;
82
+ while (number >= (nextpow = (10.0 * tenpow))) {
83
+ tenpow = nextpow;
84
+ digitcount++;
85
+ }
86
+
87
+ // minimal compensation for possible lack of precision (#7087 addition)
88
+ number *= 1 + std::numeric_limits<decltype (number)>::epsilon ();
89
+
90
+ number /= tenpow;
91
+ fillme -= digitcount;
92
+
93
+ // Pad unused cells with spaces
94
+ while (fillme-- > 0 ) {
95
+ *out++ = ' ' ;
96
+ }
97
+
98
+ // Handle negative sign
99
+ if (negative) *out++ = ' -' ;
100
+
101
+ // Print the digits, and if necessary, the decimal point
102
+ digitcount += prec;
103
+ int8_t digit = 0 ;
104
+ while (digitcount-- > 0 ) {
105
+ digit = (int8_t )number;
106
+ if (digit > 9 ) digit = 9 ; // insurance
107
+ *out++ = (char )(' 0' | digit);
108
+ if ((digitcount == prec) && (prec > 0 )) {
109
+ *out++ = ' .' ;
110
+ }
111
+ number -= digit;
112
+ number *= 10.0 ;
113
+ }
114
+
115
+ // make sure the string is terminated
116
+ *out = 0 ;
47
117
return s;
48
118
}
49
119
0 commit comments