@@ -147,7 +147,22 @@ char* ultoa( unsigned long val, char *string, int radix )
147147 return string;
148148}
149149
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) {
151166
152167 if (isnan (number)) {
153168 strcpy (s, " nan" );
@@ -158,62 +173,62 @@ char * dtostrf(double number, unsigned char width, unsigned char prec, char *s)
158173 return s;
159174 }
160175
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;
165186
166187 // Handle negative numbers
167188 if (number < 0.0 ) {
168189 *out++ = ' -' ;
169190 number = -number;
191+ if (totalWidth > 0 ) totalWidth--;
170192 }
171193
172- // The integer portion has to be <= 8 digits. Otherwise, the
173- // string is in exponent format.
194+ // Rounding up to the precision
174195 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 ) {
176203 tmp /= 10.0 ;
177- exponent++;
178- if (tmp < 10.0 ) break ;
204+ expCnt++;
179205 }
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;
191206
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;
212224 }
213225
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+ }
217231
232+ *out = 0 ; // End of string
218233 return s;
219234}
0 commit comments