HLP: sprintf corrupts the data....

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

HLP: sprintf corrupts the data....

Jump to solution
1,395 Views
tkvenki
Contributor III

/***********************/

Processor : MCF5485

IDE: CW-6.4 Build 6

/***********************/ 

 

Hi all,

 

I need a sprintf in my code to convert a float to string...

In my product there is an external interrupt every 6ms....

 

CASE1:

/***************************************************/

debugVarFloat - Array

sprintf

debugVarString - Array

/***************************************************/

 

In the above code if I observe the debugVar contents, I can see that the input is OK. But the output is corrupted sometimes....randomly.

 

 

CASE2:

/***************************************************/

debugVarFloat - Array

DISABLE_INTERRUPTS

sprintf

ENABLE_INTERRUPTS

debugVarString - Array

/***************************************************/

 In this case, both the input and output are OK. But execution of sprintf takes 10ms on my platform. So my board will not be able to respond to an external interrupt. THis is fatal to our system.

 

I tried to use the following alternatives:

1. vsnprintf - It took almost the same time as sprintf....

2. stringstreams - The same behavior was repeated...

 

 

Is there a faster way to convert a float to string?

Is there any way that I could make sprintf, corruption proof??

Please guide me through this...

 

Thanks and Regards,

Venki

Labels (1)
0 Kudos
1 Solution
526 Views
tkvenki
Contributor III

Hi Kef,

 

Thanks a lot...

I done the modification you suggested...It works fine.

Also I had a bug in my prev code....

It could not distinguish between 0.00X and 0.X/0.0X.

I have made suitable modifications, for this bug....

 

void convFloatStr(double floatVar, char* floatStr)
{
int intPart=0;
int intLen=0; 
double fractional;
char charArr[20] = {0};
char nullArr[20] = {0};  
int decimalPoint=0;
int tempInt=0;
int i=0;


if(floatVar >0)
           floatVar = floatVar + 0.000005;
else
           floatVar = floatVar - 0.000005;
    
intPart = (int)floatVar;
itoa(intPart, floatStr, 10);
intLen = strlen(floatStr);
strcat(floatStr, ".");


    if(intLen < 5)
          fractional = floatVar * 100000;
    else
          fractional = floatVar * 1000;

itoa(fractional, charArr, 10);

if(floatStr[0] != '0')
              strcat(floatStr, &charArr[intLen]);
else
{
                   while(1)
                   { 
                     tempInt = (int)(floatVar) * 10 / 1 ;
                     floatVar = ((floatVar) * 10 );
                     decimalPoint++;
                     if(tempInt) break;
                   }
                 
                   decimalPoint = decimalPoint - 2;
                   for(i=0;i<decimalPoint ;i++)
                        strcat(floatStr, "0");
                  
                   strcat(floatStr, charArr);    
}             
}

 

This code takes around 250 micro seconds on my board. A lot faster than the sprintf(10-11 milliseconds). The application works fine, without any data corruption. Thanks to all for your support.

 

 

Message Edited by tkvenki on 2009-12-02 11:52 AM

View solution in original post

0 Kudos
4 Replies
526 Views
J2MEJediMaster
Specialist I

You may need to roll your own floating-point to string conversion routine, to reduce both the time required to forma the output and reduce the memory footprint. If you're talking about converting straight binary data, I think some code has been posted in the forums to do this. For floating-point, you might want to scout around on Google.

 

---Tom

0 Kudos
526 Views
tkvenki
Contributor III

Hi,

 

Thanks for the guidance, I have rolled out a small piece of code, which will serve my purpose...

I'm posting the code below:

 

 

void convFloatStr(double floatVar, char* floatStr){int intPart=0;int intLen=0;  double fractional;char charArr[20]= {0};        intPart = (int)floatVar;itoa(intPart, floatStr, 10);intLen = strlen(floatStr);strcat(floatStr, ".");if(intLen < 5)          fractional = floatVar * 100000;else          fractional = floatVar * 1000;ltoa(fractional, charArr, 10);if(floatStr[0] != '0')              strcat(floatStr, &charArr[intLen]);else              strcat(floatStr, charArr);          }

 

 

 Please let me know if any improvements can be made to the code.

As of now the known bugs are:

 

#1

 

If I input 2.9...o/p is 2.29999

But the same is not happening with 3.9, 4.9 or 5.9.....

 

#2

Input : 9.7

Output : 9.69999

 

This strange behavior is only for a few combnation of numbers!!!!

Any suggestions on this????

 

 

 

 

 

0 Kudos
526 Views
kef
Specialist I

This is not a strange behaviour. For example 3.9 and 4.9 can't be represented exactly equal to 3.9/4.9 in binary base floating point number. Closest to 3.9 double is little below 3.9, it's 3.8999999999.. . Closest to 4.9 double is little above 4.9, it's about 4.9000000000000004 . Conversion from FP to integer in C doesn't round to closest number, it just chops the fractional part. So if you want to convert only 5 digits past dot, then you should round your floating number first, by adding 0.000005 for positive numbers, subracting 0.000005 from negative numbers.

0 Kudos
527 Views
tkvenki
Contributor III

Hi Kef,

 

Thanks a lot...

I done the modification you suggested...It works fine.

Also I had a bug in my prev code....

It could not distinguish between 0.00X and 0.X/0.0X.

I have made suitable modifications, for this bug....

 

void convFloatStr(double floatVar, char* floatStr)
{
int intPart=0;
int intLen=0; 
double fractional;
char charArr[20] = {0};
char nullArr[20] = {0};  
int decimalPoint=0;
int tempInt=0;
int i=0;


if(floatVar >0)
           floatVar = floatVar + 0.000005;
else
           floatVar = floatVar - 0.000005;
    
intPart = (int)floatVar;
itoa(intPart, floatStr, 10);
intLen = strlen(floatStr);
strcat(floatStr, ".");


    if(intLen < 5)
          fractional = floatVar * 100000;
    else
          fractional = floatVar * 1000;

itoa(fractional, charArr, 10);

if(floatStr[0] != '0')
              strcat(floatStr, &charArr[intLen]);
else
{
                   while(1)
                   { 
                     tempInt = (int)(floatVar) * 10 / 1 ;
                     floatVar = ((floatVar) * 10 );
                     decimalPoint++;
                     if(tempInt) break;
                   }
                 
                   decimalPoint = decimalPoint - 2;
                   for(i=0;i<decimalPoint ;i++)
                        strcat(floatStr, "0");
                  
                   strcat(floatStr, charArr);    
}             
}

 

This code takes around 250 micro seconds on my board. A lot faster than the sprintf(10-11 milliseconds). The application works fine, without any data corruption. Thanks to all for your support.

 

 

Message Edited by tkvenki on 2009-12-02 11:52 AM
0 Kudos