Skip to content

ATLEDGE-619: fix dtostrf #217

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 0 additions & 23 deletions cores/arduino/WString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -813,26 +813,3 @@ float String::toFloat(void) const
if (buffer) return float(atof(buffer));
return 0;
}

/*********************************************/
/* utilities functions */
/*********************************************/

int String::digitsBe4Decimal(double number)
{
int cnt = 1; // Always has one digit

// Count -ve sign as one digit
if(number < 0.0) {
cnt++;
number = -number;
}

// Count the number of digits beyond the 1st, basically, the exponent.
while(number >= 10.0) {
number /= 10;
cnt++;
}
return cnt;
}

4 changes: 0 additions & 4 deletions cores/arduino/WString.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,10 +217,6 @@ class String
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
void move(String &rhs);
#endif

// utilities functions.
// Number of digits (including sign) in the integer portion of a float/double
int digitsBe4Decimal(double number);
};

class StringSumHelper : public String
Expand Down
107 changes: 65 additions & 42 deletions cores/arduino/stdlib_noniso.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include "math.h"
#include "inttypes.h"

#define ASCII_ZERO 0x30

int atoi(const char* s) {
return (int) atol(s);
}
Expand Down Expand Up @@ -162,7 +164,31 @@ void shiftOutDigit(double *number, int count, char *s)
*number = tmp;
}

char * dtostrf(double number, signed char width, unsigned char prec, char *s) {
int digitsBe4Decimal(double number)
{
int cnt = 1; // Always has one digit

// Count -ve sign as one digit
if(number < 0.0) {
cnt++;
number = -number;
}

// Count the number of digits beyond the 1st, basically, the exponent.
while(number >= 10.0) {
number /= 10;
cnt++;
}
return cnt;
}

char *dtostrf(double number, signed char width, unsigned char prec, char *s)
{
char *out;
unsigned long long integer;
double fraction, rounding;
int digit, before, i;
int delta;

if (isnan(number)) {
strcpy(s, "nan");
Expand All @@ -173,62 +199,59 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) {
return s;
}

char *out = s;
int expCnt = 0, digit, totalWidth;
double tmp, rounding;
out = s;
before = digitsBe4Decimal(number);

// Check for left adjustment (spaces)
while(width < 0) {
*out++ = ' ';
width++;
// check if padding is required
if (width < 0) {
delta = (-width) - (before + prec + 1);
for (i = 0; i < delta; ++i) *out++ = ' ';
width = 0;
}
totalWidth = (int)width;

// Handle negative numbers
if (number < 0.0) {
*out++ = '-';
*out = '-';
number = -number;
if(totalWidth > 0) totalWidth--;
}

// Rounding up to the precision
tmp = number;
rounding = 0.5;
for(int i=0; i < prec; i++)
rounding /= 10.0;
tmp += rounding;
// seperate integral and fractional parts
integer = (unsigned long long) number;
fraction = (double) (number - integer);

// Shifting the number to the right
while( tmp >= 10.0 ) {
tmp /= 10.0;
expCnt++;
// generate chars for each digit of the integral part
i = before;
while (integer > 10) {
digit = integer % 10;
out[(i--) - 1] = ASCII_ZERO + digit;
integer /= 10;
}

// 1st, print the single digit left after shifting
digit = (int)tmp;
*out++ = '0' + digit;
tmp -= (double)digit;
if(totalWidth > 0) totalWidth--;
out[i - 1] = ASCII_ZERO + integer;
out += before;
if (!prec) goto end;

// Then the integer portion
shiftOutDigit(&tmp, expCnt, out);
out += expCnt;
if(totalWidth > 0) totalWidth -= expCnt;

// Then the decimal portion
if( prec ) {
*out++ = '.';
shiftOutDigit(&tmp, prec, out);
if(totalWidth > 0) totalWidth -= (prec + 1);
out += prec;
// rounding up to the precision
rounding = 0.5;
for (i = 0; i < prec; ++i)
rounding /= 10.0;
fraction += rounding;

// generate chars for each digit of the fractional part
*out++ = '.';
for (i = 0; i < prec; ++i) {
fraction *= 10.0;
digit = ((unsigned long long) fraction) % 10;
*out++ = (char) (ASCII_ZERO + digit);
}

// Right adjustment
while(totalWidth > 0) {
*out++ = ' ';
totalWidth--;
end:
// check if padding is required
if (width > 0) {
delta = width - (before + prec + 1);
for (i = 0; i < delta; ++i) *out++ = ' ';
}

*out = 0; // End of string
*out = 0;
return s;
}
2 changes: 2 additions & 0 deletions cores/arduino/stdlib_noniso.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ char* ultoa (unsigned long val, char *s, int radix);

char* dtostrf (double val, signed char width, unsigned char prec, char *s);

int digitsBe4Decimal(double number);

#ifdef __cplusplus
} // extern "C"
#endif
Expand Down