@@ -148,7 +148,8 @@ char* ultoa(unsigned long value, char* result, int base) {
148
148
}
149
149
150
150
char * dtostrf (double number , signed char width , unsigned char prec , char * s ) {
151
-
151
+ bool negative = false;
152
+
152
153
if (isnan (number )) {
153
154
strcpy (s , "nan" );
154
155
return s ;
@@ -158,50 +159,65 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) {
158
159
return s ;
159
160
}
160
161
161
- if (number > 4294967040.0 || number < -4294967040.0 ) {
162
- strcpy (s , "ovf" );
163
- return s ;
164
- }
165
-
166
162
char * out = s ;
167
- int signInt_Part = 1 ;
168
-
163
+
164
+ int fillme = width ; // how many cells to fill for the integer part
165
+ if (prec > 0 ) {
166
+ fillme -= (prec + 1 );
167
+ }
168
+
169
169
// Handle negative numbers
170
170
if (number < 0.0 ) {
171
- signInt_Part = -1 ;
171
+ negative = true;
172
+ fillme -- ;
172
173
number = - number ;
173
174
}
174
175
175
- // calc left over digits
176
- if (prec > 0 )
177
- {
178
- width -= (prec + 1 );
179
- }
180
-
181
176
// Round correctly so that print(1.999, 2) prints as "2.00"
182
- double rounding = 0.5 ;
177
+ // I optimized out most of the divisions
178
+ double rounding = 2.0 ;
183
179
for (uint8_t i = 0 ; i < prec ; ++ i )
184
- rounding /= 10.0 ;
180
+ rounding *= 10.0 ;
181
+ rounding = 1.0 / rounding ;
185
182
186
183
number += rounding ;
187
-
188
- // Extract the integer part of the number and print it
189
- unsigned long int_part = (unsigned long )number ;
190
- double remainder = number - (double )int_part ;
191
- out += sprintf (out , "%*ld" , width , int_part * signInt_Part );
192
-
193
- // Print the decimal point, but only if there are digits beyond
194
- if (prec > 0 ) {
195
- * out = '.' ;
196
- ++ out ;
197
-
198
-
199
- for (unsigned char decShift = prec ; decShift > 0 ; decShift -- ) {
200
- remainder *= 10.0 ;
201
- }
202
- sprintf (out , "%0*d" , prec , (int )remainder );
184
+
185
+ // Figure out how big our number really is
186
+ double tenpow = 1.0 ;
187
+ int digitcount = 1 ;
188
+ while (number >= 10.0 * tenpow ) {
189
+ tenpow *= 10.0 ;
190
+ digitcount ++ ;
191
+ }
192
+
193
+ number /= tenpow ;
194
+ fillme -= digitcount ;
195
+
196
+ // Pad unused cells with spaces
197
+ while (fillme -- > 0 ) {
198
+ * out ++ = ' ' ;
199
+ }
200
+
201
+ // Handle negative sign
202
+ if (negative ) * out ++ = '-' ;
203
+
204
+ // Print the digits, and if necessary, the decimal point
205
+ digitcount += prec ;
206
+ int8_t digit = 0 ;
207
+ while (digitcount -- > 0 ) {
208
+ digit = (int8_t )number ;
209
+ if (digit > 9 ) digit = 9 ; // insurance
210
+ * out ++ = (char )('0' | digit );
211
+ if ((digitcount == prec ) && (prec > 0 )) {
212
+ * out ++ = '.' ;
213
+ }
214
+ number -= digit ;
215
+ number *= 10.0 ;
203
216
}
204
217
218
+ // make sure the string is terminated
219
+ * out = 0 ;
205
220
return s ;
206
221
}
207
222
223
+
0 commit comments