Performance with dtostrf()

I'm calling dtostrf() around 20 time in my program to do some fancy formatting. The function works well and does what i need, but slows my code way down (like several milliseconds per dtostrf() call)

If i just comment out my dtostrf() function, the program runs much faster. I can probably live with the slow performance, but it seems odd.

Anyone have similar experience with performance of dtostrf()

thanks in advance.

Kris

I'm calling dtostrf() around 20 time in my program

, which I couldn't be arsed to post for people to read, 'cos it's secret

KrisKasprzak:
I'm calling dtostrf() around 20 time in my program to do some fancy formatting. The function works well and does what i need, but slows my code way down (like several milliseconds per dtostrf() call)

Maybe something like this would be better:

float myFloat = 12.345;
char myBuffer[15];

// let's say we want four figures past the decimal point
long myFixed = (myFloat * 10000.0) + 0.5;
sprintf(myBuffer, "%d.%04d", (myFixed/10000L), (myFixed%10000L));

Note: this code does not handle negative numbers.

KrisKasprzak:
I'm calling dtostrf() around 20 time in my program to do some fancy formatting.

Anyone have similar experience with performance of dtostrf()

Yes. I guess you just have to balance the need for fancy formatting against the seriousness of the problem. The anticipated output of your sensors might have a bearing on the former.

performance of dtostrf()

On which Arduino? I saw recently that on the ARM boards, dtostrf() calls sprintf() (or something like that), while on AVR it is a highly optimized bit of assembler code.

odometer:
Maybe something like this would be better:

float myFloat = 12.345;

char myBuffer[15];

// let's say we want four figures past the decimal point
long myFixed = (myFloat * 10000.0) + 0.5;
sprintf(myBuffer, "%d.%04d", (myFixed/10000L), (myFixed%10000L));



Note: this code **does not** handle negative numbers.

+1 for odometer

Note that the modulo % could be derived from the division with one var and one subtract.
saves some extra time

long myFixed = (myFloat * 10000.0) + 0.5;
long dd = myFixed/10000L;
long mm = myFixed - dd;
sprintf(myBuffer, "%d.%04d", dd, mm); // mind the leading zeros of the decimals!!

KrisKasprzak:
I’m calling dtostrf() around 20 time in my program to do some fancy formatting. The function works well and does what i need, but slows my code way down (like several milliseconds per dtostrf() call)

If i just comment out my dtostrf() function, the program runs much faster. I can probably live with the slow performance, but it seems odd.

Anyone have similar experience with performance of dtostrf()

No, not at all!
When I do a timing test for dtostrf() on an Arduino UNO, I find that the function call takes about 136 microseconds (= 0.136 milliseconds).

void setup() {
  Serial.begin(115200);
  float f;
  char str[21];
  for (int i=0;i<=1000;i++)
  {
    f=PI*i;
    unsigned long time=micros();
    dtostrf(f,8,5,str);
    time=micros()-time;
    Serial.print("PI * ");Serial.print(i);Serial.print("=\t");
    Serial.print(str);Serial.print("\ttime= ");Serial.println(time);
  }
}

void loop() 
{
}

And this timing includes the time that is required by one function call of “micros()” as well!

If you measure “several milliseconds per dtostrf() call” you must be doing wrong.

In Germany we have a saying: “Wer misst misst Mist”
The English meaning of that is: “Who measures measures crap”
That’s perhaps what you are doing.

But it’s hard to say as you are avoiding to post any line of the crap code you are using.

Or are you perhaps operating a 1MHz “Atmega on a breadboard”?
With 1 MHz controller clock and an Atmega, the timing should increase by factor 16.
If so, then you are indeed in the range of more than 2 milliseconds.
But with a typical Atmega board and 16 MHz clocking, dtostrf() should be much less than 1 millisecond.

alternative, but I do not know if it’s faster

char* itoa(char* c, int szc, int n)
{
    char* en;
	   int s = n;
	   char sig = '\0';
	   if (n<0)
	   {
	   	    sig = '-';
	   	    n = -n;
	   }
	   
	   char* r = c;
	   while (n && szc--)
	   {
	       *c++ = (n%10) + '0';
	   	    n /= 10;
	   }
	   
	   if (sig)
	      *c++ = sig;
	   *c = '\0';
	   en = c--;
	   
	   while( c > r)
	   {
	   	    *c ^= *r;
	   	    *r ^= *c;
	   	    *c ^= *r;
	   	    --c;
	   	    ++r;
	   }
	   
	   return en;
}

char* ftoa(char *s, int szc, float f, const unsigned int precision)
{
    int p[] = { 0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
    int n = (int)f;
    char* st = s;
 
    s = itoa(s, szc, n);
    *s++ = '.';
    n = abs((int)((f - n) * p[precision]));
    s = itoa(s, szc - (s-st) - 1, n);
    
    return s;
}