Go Down

Topic: dtostrf() conversion function problems?  (Read 14576 times) previous topic - next topic

odometer

If you can help on the left padding, it will be appreciated ! :-) (and people on ESP will too !)
About "ovt", I'm not following you since probably because I'm not here since the begin of the thread ...
I wrote "ovf" -- as in "overflow". (Try formatting a number like 5000000000, that is, five billion.)

Anyway, try this. (I haven't tested it yet; if you find any bugs, please tell me.)

Code: [Select]

char * dtostrf(double number, signed char width, unsigned char prec, char *s) {

    if (isnan(number)) {
        strcpy(s, "nan");
        return s;
    }
    if (isinf(number)) {
        strcpy(s, "inf");
        return s;
    }

    char* out = s;
   
    int fillme = width; // how many cells to fill for the integer part
    if (prec > 0) {
        fillme -= (prec+1);
    } 
   
    // Handle negative numbers
    if (number < 0.0) {
        *out++ = '-';
        fillme--;
        number = -number;
    }

    // Round correctly so that print(1.999, 2) prints as "2.00"
    // I optimized out most of the divisions
    double rounding = 2.0;
    for (uint8_t i = 0; i < prec; ++i)
        rounding *= 10.0;     
    rounding = 1.0 / rounding; 

    number += rounding;
   
    // Figure out how big our number really is
    double tenpow = 1.0;
    int digitcount = 1;
    while (number >= 10.0 * tenpow) {
        tenpow *= 10.0;   
        digitcount++;
    }
   
    number /= tenpow;
    fillme -= digitcount;
   
    // Pad unused cells with spaces
    while (fillme-- > 0) {
        *out++ = ' ';
    }
   
    // Print the digits, and if necessary, the decimal point
    digitcount += prec;
    int8_t digit = 0;
    while (digitcount-- > 0) {       
        digit = (int8_t)number;
        if (digit > 9) digit = 9; // insurance
        *out++ = (char)('0' | digit);
        if ((digitcount == prec) && (prec > 0)) {
            *out++ = '.';
        }   
        number -= digit;
        number *= 10.0;
    }

    // make sure the string is terminated
    *out = 0;
    return s;
}

martinayotte

#46
Aug 08, 2015, 09:23 pm Last Edit: Aug 08, 2015, 09:23 pm by martinayotte
Hi Odometer,

Thanks for you work !

So, for OVF, if I understand, the previous code was useless. I've tested the 5 million and it is working.

I've tested few other cases, and left pad is working (I'm glad with the way you've done it), I've only postponed the negative sign after the left padding, I think it is nicer (I did that simply by setting a boolean and do the concat of '-' later).

I've not found any bug yet, so I think I will commit this version to the current PR for ESP8266.

Thanks a lot for your contribution,
Regards,
Martin

Go Up