2424#include " math.h"
2525#include " inttypes.h"
2626
27+ #define ASCII_ZERO 0x30
28+
2729int atoi (const char * s) {
2830 return (int ) atol (s);
2931}
@@ -162,7 +164,31 @@ void shiftOutDigit(double *number, int count, char *s)
162164 *number = tmp;
163165}
164166
165- char * dtostrf (double number, signed char width, unsigned char prec, char *s) {
167+ int digitsBe4Decimal (double number)
168+ {
169+ int cnt = 1 ; // Always has one digit
170+
171+ // Count -ve sign as one digit
172+ if (number < 0.0 ) {
173+ cnt++;
174+ number = -number;
175+ }
176+
177+ // Count the number of digits beyond the 1st, basically, the exponent.
178+ while (number >= 10.0 ) {
179+ number /= 10 ;
180+ cnt++;
181+ }
182+ return cnt;
183+ }
184+
185+ char *dtostrf (double number, signed char width, unsigned char prec, char *s)
186+ {
187+ char *out;
188+ unsigned long long integer;
189+ double fraction, rounding;
190+ int digit, before, i;
191+ int delta;
166192
167193 if (isnan (number)) {
168194 strcpy (s, " nan" );
@@ -173,62 +199,59 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) {
173199 return s;
174200 }
175201
176- char *out = s;
177- int expCnt = 0 , digit, totalWidth;
178- double tmp, rounding;
202+ out = s;
203+ before = digitsBe4Decimal (number);
179204
180- // Check for left adjustment (spaces)
181- while (width < 0 ) {
182- *out++ = ' ' ;
183- width++;
205+ // check if padding is required
206+ if (width < 0 ) {
207+ delta = (-width) - (before + prec + 1 );
208+ for (i = 0 ; i < delta; ++i) *out++ = ' ' ;
209+ width = 0 ;
184210 }
185- totalWidth = (int )width;
186211
187212 // Handle negative numbers
188213 if (number < 0.0 ) {
189- *out++ = ' -' ;
214+ *out = ' -' ;
190215 number = -number;
191- if (totalWidth > 0 ) totalWidth--;
192216 }
193217
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;
218+ // seperate integral and fractional parts
219+ integer = (unsigned long long ) number;
220+ fraction = (double ) (number - integer);
200221
201- // Shifting the number to the right
202- while ( tmp >= 10.0 ) {
203- tmp /= 10.0 ;
204- expCnt++;
222+ // generate chars for each digit of the integral part
223+ i = before;
224+ while (integer > 10 ) {
225+ digit = integer % 10 ;
226+ out[(i--) - 1 ] = ASCII_ZERO + digit;
227+ integer /= 10 ;
205228 }
206229
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--;
230+ out[i - 1 ] = ASCII_ZERO + integer;
231+ out += before;
232+ if (!prec) goto end;
212233
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;
234+ // rounding up to the precision
235+ rounding = 0.5 ;
236+ for (i = 0 ; i < prec; ++i)
237+ rounding /= 10.0 ;
238+ fraction += rounding;
239+
240+ // generate chars for each digit of the fractional part
241+ *out++ = ' .' ;
242+ for (i = 0 ; i < prec; ++i) {
243+ fraction *= 10.0 ;
244+ digit = ((unsigned long long ) fraction) % 10 ;
245+ *out++ = (char ) (ASCII_ZERO + digit);
224246 }
225247
226- // Right adjustment
227- while (totalWidth > 0 ) {
228- *out++ = ' ' ;
229- totalWidth--;
248+ end:
249+ // check if padding is required
250+ if (width > 0 ) {
251+ delta = width - (before + prec + 1 );
252+ for (i = 0 ; i < delta; ++i) *out++ = ' ' ;
230253 }
231254
232- *out = 0 ; // End of string
255+ *out = 0 ;
233256 return s;
234257}
0 commit comments