Serial.print(float) is buggy...?

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

-arne

file: ./hardware/cores/arduino/Print.cpp

function Print::printFloat() should be changed:

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... :slight_smile:

-arne

seems to work:

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

i like this even better:

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

this line:

if (number >= 1) digits--

misses a semicolon at its end...

-arne