@@ -162,7 +162,31 @@ void shiftOutDigit(double *number, int count, char *s)
162162 *number = tmp;
163163}
164164
165- char * dtostrf (double number, signed char width, unsigned char prec, char *s) {
165+ int digitsBe4Decimal (double number)
166+ {
167+ int cnt = 1 ; // Always has one digit
168+
169+ // Count -ve sign as one digit
170+ if (number < 0.0 ) {
171+ cnt++;
172+ number = -number;
173+ }
174+
175+ // Count the number of digits beyond the 1st, basically, the exponent.
176+ while (number >= 10.0 ) {
177+ number /= 10 ;
178+ cnt++;
179+ }
180+ return cnt;
181+ }
182+
183+ char *dtostrf (double number, signed char width, unsigned char prec, char *s)
184+ {
185+ char *out;
186+ unsigned long long integer;
187+ double fraction, rounding;
188+ int digit, before, i;
189+ int delta;
166190
167191 if (isnan (number)) {
168192 strcpy (s, " nan" );
@@ -173,62 +197,59 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) {
173197 return s;
174198 }
175199
176- char *out = s;
177- int expCnt = 0 , digit, totalWidth;
178- double tmp, rounding;
200+ out = s;
201+ before = digitsBe4Decimal (number);
179202
180- // Check for left adjustment (spaces)
181- while (width < 0 ) {
182- *out++ = ' ' ;
183- width++;
203+ // check if padding is required
204+ if (width < 0 ) {
205+ delta = (-width) - (before + prec + 1 );
206+ for (i = 0 ; i < delta; ++i) *out++ = ' ' ;
207+ width = 0 ;
184208 }
185- totalWidth = (int )width;
186209
187210 // Handle negative numbers
188211 if (number < 0.0 ) {
189- *out++ = ' -' ;
212+ *out = ' -' ;
190213 number = -number;
191- if (totalWidth > 0 ) totalWidth--;
192214 }
193215
194- // Rounding up to the precision
195- tmp = number;
196- rounding = 0.5 ;
197- for (int i=0 ; i < prec; i++)
198- rounding /= 10.0 ;
199- tmp += rounding;
216+ // seperate integral and fractional parts
217+ integer = (unsigned long long ) number;
218+ fraction = (double ) (number - integer);
200219
201- // Shifting the number to the right
202- while ( tmp >= 10.0 ) {
203- tmp /= 10.0 ;
204- expCnt++;
220+ // generate chars for each digit of the integral part
221+ i = before;
222+ while (integer > 10 ) {
223+ digit = integer % 10 ;
224+ out[(i--) - 1 ] = ' 0' + digit;
225+ integer /= 10 ;
205226 }
206227
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--;
228+ out[i - 1 ] = ' 0' + integer;
229+ out += before;
230+ if (!prec) goto end;
212231
213- // Then the integer portion
214- shiftOutDigit (&tmp, expCnt, out);
215- out += expCnt;
216- if (totalWidth > 0 ) totalWidth -= expCnt;
232+ // rounding up to the precision
233+ rounding = 0.5 ;
234+ for (i = 0 ; i < prec; ++i)
235+ rounding /= 10.0 ;
236+ fraction += rounding;
217237
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 ;
238+ // generate chars for each digit of the fractional part
239+ *out++ = ' . ' ;
240+ for (i = 0 ; i < prec; ++i) {
241+ fraction *= 10.0 ;
242+ digit = (( int ) fraction) % 10 ;
243+ *out++ = ' 0 ' + digit ;
224244 }
225245
226- // Right adjustment
227- while (totalWidth > 0 ) {
228- *out++ = ' ' ;
229- totalWidth--;
246+ end:
247+ // check if padding is required
248+ if (width > 0 ) {
249+ delta = width - (before + prec + 1 );
250+ for (i = 0 ; i < delta; ++i) *out++ = ' ' ;
230251 }
231252
232- *out = 0 ; // End of string
253+ *out = 0 ;
233254 return s;
234255}
0 commit comments