Skip to content

Commit f762721

Browse files
Use sprintf to output floats in Print/dtostrf
Fixes #7043 Two slightly different custom routines were implemented by hand in dtostrf (an AVR-lib non-ISO function) and Print. This resulted in inconsistent output of float/double vars when rounding was needed. Replace them all with a call to sprintf(), removing the duplicated, not quite correct code. Print(String(float)) and Print(float) now generate the same output.
1 parent 56b90a2 commit f762721

File tree

3 files changed

+8
-112
lines changed

3 files changed

+8
-112
lines changed

Diff for: cores/esp8266/Print.cpp

+2-43
Original file line numberDiff line numberDiff line change
@@ -268,47 +268,6 @@ size_t Print::printNumber(unsigned long n, uint8_t base) {
268268
}
269269

270270
size_t Print::printFloat(double number, uint8_t digits) {
271-
size_t n = 0;
272-
273-
if(isnan(number))
274-
return print("nan");
275-
if(isinf(number))
276-
return print("inf");
277-
if(number > 4294967040.0)
278-
return print("ovf"); // constant determined empirically
279-
if(number < -4294967040.0)
280-
return print("ovf"); // constant determined empirically
281-
282-
// Handle negative numbers
283-
if(number < 0.0) {
284-
n += print('-');
285-
number = -number;
286-
}
287-
288-
// Round correctly so that print(1.999, 2) prints as "2.00"
289-
double rounding = 0.5;
290-
for(uint8_t i = 0; i < digits; ++i)
291-
rounding /= 10.0;
292-
293-
number += rounding;
294-
295-
// Extract the integer part of the number and print it
296-
unsigned long int_part = (unsigned long) number;
297-
double remainder = number - (double) int_part;
298-
n += print(int_part);
299-
300-
// Print the decimal point, but only if there are digits beyond
301-
if(digits > 0) {
302-
n += print(".");
303-
}
304-
305-
// Extract digits from the remainder one at a time
306-
while(digits-- > 0) {
307-
remainder *= 10.0;
308-
int toPrint = int(remainder);
309-
n += print(toPrint);
310-
remainder -= toPrint;
311-
}
312-
313-
return n;
271+
char buf[40];
272+
return write(dtostrf(number, 0, digits, buf));
314273
}

Diff for: cores/esp8266/Print.h

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
#include "WString.h"
2727
#include "Printable.h"
2828

29+
#include "stdlib_noniso.h"
30+
2931
#define DEC 10
3032
#define HEX 16
3133
#define OCT 8

Diff for: cores/esp8266/core_esp8266_noniso.cpp

+4-69
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
2323
*/
2424

25+
#include <stdio.h>
2526
#include <stdlib.h>
2627
#include <string.h>
2728
#include <stdbool.h>
@@ -40,75 +41,9 @@ char* ultoa(unsigned long value, char* result, int base) {
4041
}
4142

4243
char * dtostrf(double number, signed char width, unsigned char prec, char *s) {
43-
bool negative = false;
44-
45-
if (isnan(number)) {
46-
strcpy(s, "nan");
47-
return s;
48-
}
49-
if (isinf(number)) {
50-
strcpy(s, "inf");
51-
return s;
52-
}
53-
54-
char* out = s;
55-
56-
int fillme = width; // how many cells to fill for the integer part
57-
if (prec > 0) {
58-
fillme -= (prec+1);
59-
}
60-
61-
// Handle negative numbers
62-
if (number < 0.0) {
63-
negative = true;
64-
fillme--;
65-
number = -number;
66-
}
67-
68-
// Round correctly so that print(1.999, 2) prints as "2.00"
69-
// I optimized out most of the divisions
70-
double rounding = 2.0;
71-
for (uint8_t i = 0; i < prec; ++i)
72-
rounding *= 10.0;
73-
rounding = 1.0 / rounding;
74-
75-
number += rounding;
76-
77-
// Figure out how big our number really is
78-
double tenpow = 1.0;
79-
int digitcount = 1;
80-
while (number >= 10.0 * tenpow) {
81-
tenpow *= 10.0;
82-
digitcount++;
83-
}
84-
85-
number /= tenpow;
86-
fillme -= digitcount;
87-
88-
// Pad unused cells with spaces
89-
while (fillme-- > 0) {
90-
*out++ = ' ';
91-
}
92-
93-
// Handle negative sign
94-
if (negative) *out++ = '-';
95-
96-
// Print the digits, and if necessary, the decimal point
97-
digitcount += prec;
98-
int8_t digit = 0;
99-
while (digitcount-- > 0) {
100-
digit = (int8_t)number;
101-
if (digit > 9) digit = 9; // insurance
102-
*out++ = (char)('0' | digit);
103-
if ((digitcount == prec) && (prec > 0)) {
104-
*out++ = '.';
105-
}
106-
number -= digit;
107-
number *= 10.0;
108-
}
109-
110-
// make sure the string is terminated
111-
*out = 0;
44+
char fmt[32];
45+
sprintf(fmt, "%%%d.%df", width, prec);
46+
sprintf(s, fmt, number);
11247
return s;
11348
}
11449

0 commit comments

Comments
 (0)