Go Down

Topic: Serial.print(float) is buggy...? (Read 1 time) previous topic - next topic

RIDDICK

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1273397489/0#8

-arne

RIDDICK

#1
May 09, 2010, 01:44 pm Last Edit: May 09, 2010, 02:03 pm by RIDDICK Reason: 1
file: ./hardware/cores/arduino/Print.cpp

function Print::printFloat() should be changed:
Code: [Select]

void Print::printFloat(double number, uint8_t digits)
{
 if (number == 0) {
   print("0e0");
   return;
 }
 // Handle negative numbers
 if (number < 0) {
    print('-');
    number = -number;
 }
 // determine exponent
 const int8_t e = log(number) / log(10) - 8;
 number *= pow(10,-e);
 print((uint32_t)number);
 print('e');
 print(e);
}

*wag tail*

untested... :-)

-arne

RIDDICK

#2
May 09, 2010, 01:51 pm Last Edit: May 10, 2010, 10:26 am by RIDDICK Reason: 1
seems to work:
Code: [Select]
void setup() {
 Serial.begin(115200);
}

void printFloat(double number, uint8_t digits)
{
 // Handle negative numbers
 if (number < 0) {
    Serial.print('-');
    number = -number;
 }
 // determine exponent
 if (number >= 1) digits--;
 const int8_t e = log(number) / log(10) - digits;
 number *= pow(10,-e);
 Serial.print((uint32_t)number);
 Serial.print('e');
 Serial.print(e);
}

void loop() {
 for (float f=0; f<1e30; f = (f+1)*12.34) {
   Serial.print(f);
   Serial.print(' ');
   printFloat(f,0);
   Serial.print(' ');
   printFloat(-f,0);
   Serial.println();
 }
}


-arne

RIDDICK

#3
May 09, 2010, 02:29 pm Last Edit: May 10, 2010, 10:01 am by RIDDICK Reason: 1
i like this even better:
Code: [Select]
void setup() { Serial.begin(115200); }

void printFloat(double number, int8_t digits) {
 if (number == 0) { Serial.print('0'); return; }
 if (number < 0) { Serial.print('-'); number = -number; } // handle negative numbers
 int8_t e = log(number) * (1/log(10)); // determine exponent
 if (digits > 7) digits = 7; else if (digits < 1) digits = 1; // shape digits
 if (number >= 1) digits--
 number += .5 * pow(10,e-digits); // rounding
 // print out
 if (e >= digits) {
   e -= digits;
   number *= pow(10,-e);
   Serial.print((uint32_t)number);
   for (; e>0; e--) Serial.print('0');
 } else {
   const uint32_t I = (uint32_t) number;
   number -= I;
   Serial.print(I);
   uint32_t F = (uint32_t) (number * pow(10,digits-e));
   if (F == 0) return;
   Serial.print('.');
   for (; e<0; e++) Serial.print('0');
   while (F % 10 == 0) F /= 10;
   Serial.print(F);
 }
}

void loop() {
 for (float f=1e-30; f<1e30; f*=12.34) {
   Serial.print(f);
   Serial.print(' ');
   printFloat(f,3);
   Serial.print(' ');
   printFloat(f,100);
   Serial.println();
 }
}

it is more readable and honors the digits parameter...

EDIT: added rounding (tested OK)...  [smiley=beer.gif]

-arne

RIDDICK

this line:
Code: [Select]
if (number >= 1) digits--
misses a semicolon at its end...

-arne

Go Up