@@ -162,7 +162,31 @@ void shiftOutDigit(double *number, int count, char *s)
162
162
*number = tmp;
163
163
}
164
164
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;
166
190
167
191
if (isnan (number)) {
168
192
strcpy (s, " nan" );
@@ -173,62 +197,59 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) {
173
197
return s;
174
198
}
175
199
176
- char *out = s;
177
- int expCnt = 0 , digit, totalWidth;
178
- double tmp, rounding;
200
+ out = s;
201
+ before = digitsBe4Decimal (number);
179
202
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 ;
184
208
}
185
- totalWidth = (int )width;
186
209
187
210
// Handle negative numbers
188
211
if (number < 0.0 ) {
189
- *out++ = ' -' ;
212
+ *out = ' -' ;
190
213
number = -number;
191
- if (totalWidth > 0 ) totalWidth--;
192
214
}
193
215
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);
200
219
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 ;
205
226
}
206
227
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;
212
231
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;
217
237
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 ;
224
244
}
225
245
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++ = ' ' ;
230
251
}
231
252
232
- *out = 0 ; // End of string
253
+ *out = 0 ;
233
254
return s;
234
255
}
0 commit comments