Problem with float only storing 2 decimal points

I'm having issues with Float type.

If I declare it only hold the first two decimal points in this case below, 0.28. Any idea why?

float testvar=(float) 0.2823762;
 Serial.print(testvar);

//Prints 0.28
// Also tried float testvar= 0.2823762; without (float).

Hi 3en,

As far as i know the serial.print will print up to 2 decimal points. The value is still what you declare it to be, it's just not coming through the serial.

Jeroen

edit, from serial reference

Printing of floats is supported with a precision of two places to the right of the decimal point.

Thanks Yot! I guess that makes sense. Though kind of annoying as I'm trying to implement some audio filters on the Arduino and I'm going to have to work blind once I convert the audio input values to a float from -1 to 1.

You can use sprintf to convert the float to a string, with as many decimal places as you want. Then, Serial.print that string, instead.

You can use sprintf to convert …

Last time I checked, the code for “%f” formatting was not supported by the AVR library. This I understand was deliberate based on a code size/benefit assesment. The problem here is that the format is evaluated at runtime and so all variations must be accounted for. As I see it, excluding it makes sence (it keeps the static import library compact). You can alway grab the source somewhere else and include the bits you actually need.

I’m currently trying to solve my problem. But I’m run into another problem with some Long variable maths where the Arduino is not outputting the correct/expected value.

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

The code so far which should require no use of any libraries and should work with (0.values…).
//This code does not work. Until the math functions have been fixed

//This is a function

void serial_printFloat(float value) {
  //Check if negative value and print - sign

  if(value<0)
  {Serial.print("-");}
  //Print the number before the decimal point
  
  //We check if the number before the decimal point
  //is negative. If it is then we make it into a positive
  //number. So we don't get something like --10.286
  //As we already printed the negative sign (-)
  int temp0=(int)value;
  if(temp0<0){
    temp0=temp0-(temp0*2);
  }
  Serial.print(temp0);
  //Print decimal point
  Serial.print(".");
  //We insert the numbers after the deciaml (.) into temp
  //Using long as we can store more values
  //Add additional zeros (000) to 1000000 to increase degree of accuracy
  //beyond the decimal point
  long temp=long((value - (long)value) * 1000000);
  
  //If temp is negative we convert it to a positive number so we
  //don't get something like -0.-286

  if(temp<0){
    temp=temp-(temp*2);
   }
   
  Serial.println(temp);
  
  //And that's it. We're done :-)
  
}

You can also find the Print class implementation of printFloat(double number, uint8_t digits) in this file... \arduino-0017\hardware\cores\arduino\Print.cpp (line 182)

No need to invent your own function, just copy this one.

Unfortunately it's a private member function, which makes it non-trivial (for me) to derive a new class that exposes it. Anybody else have a good example of how easily to derive a new class that exposes the Print::printFloat method? Inheritance is not my strength.

Thanks Mitch.

For now I’ve copy and pasted the function.

The question now how do I determine a how many number exist after a decimal point in a float. Because this function requires that number.

And I can’t just give the function a blanket digit like 4 when the float only has 2 numbers after the decimal point because the function will otherwise output some random numbers which changes the value of the float instead of just filling with zeros (0).

void printFloat(double number, uint8_t digits) 
{ 
  // Handle negative numbers
  if (number < 0.0)
  {
     Serial.print('-');
     number = -number;
  }

  // Round correctly so that print(1.999, 2) prints as "2.00"
  double rounding = 0.5;
  for (uint8_t i=0; i<digits; ++i)
    rounding /= 10.0;
  
  number += rounding;

  // Extract the integer part of the number and print it
  unsigned long int_part = (unsigned long)number;
  double remainder = number - (double)int_part;
  Serial.print(int_part);

  // Print the decimal point, but only if there are digits beyond
  if (digits > 0)
    Serial.print("."); 

  // Extract digits from the remainder one at a time
  while (digits-- > 0)
  {
    remainder *= 10.0;
    int toPrint = int(remainder);
    Serial.print(toPrint);
    remainder -= toPrint; 
  } 
}

how do I determine a how many number exist after a decimal point in a float.

The 32bit floating point numbers used by arduino ALWAYS contain about 6 or 7 digits worth of precision; how many come "after" the decimal point depends on how many are before the decimal point. You should be able to get real close to 3.141592, but you can't get 20000000000.5

In your initial message, you are misled because serial.Print() only prints two decimal places, regardless of the actual number. For example, the sketch:

void setup()
{
  Serial.begin(9600);
}
void loop()
{
  float testvar = 0.2823762;
  Serial.println(testvar);
  Serial.println(testvar*10.0);
  Serial.println(testvar*100.0);
  Serial.println(testvar*1000.0);
  Serial.println(testvar*10000.0);
  Serial.println(testvar*100000.0);
  Serial.println(testvar*1000000.0);
  delay(20000);
}

will print out

0.28
2.82
28.24
282.38
2823.76
28237.62
282376.18

Showing that all of the digits ARE there. (well, accurate to 7 digits, approximately.) Note that each value is rounded...

Thanks westfw. I guess I can live with some inaccuracies rounding. I wonder though if there is a way to truncate so we get the correct number by number output.

Though for the people who have Google this problem and got this post.

Other various solutions/information on this can be found on:

http://www.arduino.cc/playground/Code/PrintFloats http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1164927646