@@ -147,7 +147,22 @@ char* ultoa( unsigned long val, char *string, int radix )
147
147
return string;
148
148
}
149
149
150
- char * dtostrf (double number, unsigned char width, unsigned char prec, char *s) {
150
+ void shiftOutDigit (double *number, int count, char *s)
151
+ {
152
+ double tmp = *number;
153
+ int digit;
154
+
155
+ while ( count ) {
156
+ tmp *= 10.0 ;
157
+ digit = (int )tmp;
158
+ *s++ = ' 0' + digit;
159
+ tmp -= (double )digit;
160
+ count--;
161
+ }
162
+ *number = tmp;
163
+ }
164
+
165
+ char * dtostrf (double number, signed char width, unsigned char prec, char *s) {
151
166
152
167
if (isnan (number)) {
153
168
strcpy (s, " nan" );
@@ -158,62 +173,62 @@ char * dtostrf(double number, unsigned char width, unsigned char prec, char *s)
158
173
return s;
159
174
}
160
175
161
- char * out = s;
162
- int exponent = 0 ;
163
- unsigned char len, expLen;
164
- double tmp;
176
+ char *out = s;
177
+ int expCnt = 0 , digit, totalWidth;
178
+ double tmp, rounding;
179
+
180
+ // Check for left adjustment (spaces)
181
+ while (width < 0 ) {
182
+ *out++ = ' ' ;
183
+ width++;
184
+ }
185
+ totalWidth = (int )width;
165
186
166
187
// Handle negative numbers
167
188
if (number < 0.0 ) {
168
189
*out++ = ' -' ;
169
190
number = -number;
191
+ if (totalWidth > 0 ) totalWidth--;
170
192
}
171
193
172
- // The integer portion has to be <= 8 digits. Otherwise, the
173
- // string is in exponent format.
194
+ // Rounding up to the precision
174
195
tmp = number;
175
- for (;;) {
196
+ rounding = 0.5 ;
197
+ for (int i=0 ; i < prec; i++)
198
+ rounding /= 10.0 ;
199
+ tmp += rounding;
200
+
201
+ // Shifting the number to the right
202
+ while ( tmp >= 10.0 ) {
176
203
tmp /= 10.0 ;
177
- exponent++;
178
- if (tmp < 10.0 ) break ;
204
+ expCnt++;
179
205
}
180
- if (exponent > 8 )
181
- number = tmp;
182
- else
183
- exponent = 0 ;
184
-
185
- // Round correctly so that print(1.999, 2) prints as "2.00"
186
- double rounding = 0.5 ;
187
- for (uint8_t i = 0 ; i < prec; ++i)
188
- rounding /= 10.0 ;
189
-
190
- number += rounding;
191
206
192
- // Extract the integer part of the number and print it
193
- unsigned long int_part = (unsigned long )number;
194
- double remainder = number - (double )int_part;
195
- out += sprintf (out, " %ld" , int_part);
196
-
197
- // Don't go beyond the given width of the string
198
- len = (unsigned char )(out - s);
199
- expLen = (exponent == 0 ) ? 0 : 5 ; // 5 places for exponent expression
200
- if ((prec + len + expLen) > width)
201
- prec = width - len - expLen;
202
-
203
- // Print the decimal point, but only if there are digits beyond
204
- if (prec > 0 ) {
205
- *out++ = ' .' ;
206
- // Copy character by character to 'out' string
207
- for (unsigned char decShift = prec; decShift > 0 ; decShift--) {
208
- remainder *= 10.0 ;
209
- out += sprintf (out, " %d" , (int )remainder );
210
- remainder -= (double )(int )remainder ;
211
- }
207
+ // 1st, print the single digit left after shifting
208
+ digit = (int )tmp;
209
+ *out++ = ' 0' + digit;
210
+ tmp -= (double )digit;
211
+ if (totalWidth > 0 ) totalWidth--;
212
+
213
+ // Then the integer portion
214
+ shiftOutDigit (&tmp, expCnt, out);
215
+ out += expCnt;
216
+ if (totalWidth > 0 ) totalWidth -= expCnt;
217
+
218
+ // Then the decimal portion
219
+ if ( prec ) {
220
+ *out++ = ' .' ;
221
+ shiftOutDigit (&tmp, prec, out);
222
+ if (totalWidth > 0 ) totalWidth -= (prec + 1 );
223
+ out += prec;
212
224
}
213
225
214
- // Print the exponent if exists
215
- if (exponent)
216
- sprintf (out, " e+%.3d" , exponent);
226
+ // Right adjustment
227
+ while (totalWidth > 0 ) {
228
+ *out++ = ' ' ;
229
+ totalWidth--;
230
+ }
217
231
232
+ *out = 0 ; // End of string
218
233
return s;
219
234
}
0 commit comments