Rounding when printing

I can't find the reference on how the print() function handles floats. I've been under the impression that if

a = 1.346
print(a) // would print out 1.34

and

print(a + .005) // would print out 1.35

my question is, in the case of floats, does the print() function round the argument before printing?

You could look in Print.cpp which on my Windows PC is in C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino\

size_t Print::print(double n, int digits)
{
  return printFloat(n, digits);
}
size_t Print::printFloat(double number, uint8_t digits) 
{ 
  size_t n = 0;
  
  if (isnan(number)) return print("nan");
  if (isinf(number)) return print("inf");
  if (number > 4294967040.0) return print ("ovf");  // constant determined empirically
  if (number <-4294967040.0) return print ("ovf");  // constant determined empirically
  
  // Handle negative numbers
  if (number < 0.0)
  {
     n += 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;
  n += print(int_part);

  // Print the decimal point, but only if there are digits beyond
  if (digits > 0) {
    n += print('.'); 
  }

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

with sprintf() you can specify the number of decimal digits (e.g. %5.2f )

my question is, in the case of floats, does the print() function round the argument before printing?

If you have an Arduino this would be very easy to check for yourself.

Define a float as 1.23456 and see how it prints with two decimal places.

Then define the float as 1.23567 or 1.23678 and see what the difference is.

gcjr, why would I want to use sprintf() when I can use print(a,b) ?

srnet, absolutely but I thought I might get a little insight to rounding rather than truncating. My code answered the easy part of my question.

UKHeliBob, remind me to tell you a test pilot joke about Boscombe Down someday.

because it's the standard print function in C (but not Arduino C) and can format a complete line containing multiple variables and text with as much precision as you would like. See Hello World, the first program described in The C Progamming Language

See Hello World, the first program described in The C Progamming Language

But that does not use sprintf() and in any case, sprintf() on most Arduinos does not support the %f parameter

sprintf() is surely way over the top for printing a single float

gcjr:
with sprintf() you can specify the number of decimal digits (e.g. %5.2f )

You're new around here, aren't you?

you're right. i forgot they stripped support for %f from sprintf(). but i have a hard time remembering dtof().

but i also assume that more than a single float needs to be printed.

The fact that different boards support different print functions can be confusing. I have been using an ESP32 recently and find Serial.printf() with floats very useful, for instance. Then I swap to a Nano and miss it

i also assume that more than a single float needs to be printed.

As usual it is horses for courses

UKHeliBob:
The fact that different boards support different print functions can be confusing.

printf() is very standard. the Arduino is the exception.

the Arduino is the exception.

Yes, but it does not have a console to output anything too so printf() alone would be of no use, hence the Serial.printf() fudge for the ESP32. Then, of course, there is the problem of most Arduinos having very little memory to work with, hence the lack of support for the %f format specifier in sprintf()

the esp32 supports printf() (w/o the Serial prefix)

but if your formatting for other devices such as LCD, OLED, Serial[1-4] or across WiFi or Bluetooth, sprintf() is more useful.

is dtof() that much more efficient than the %f support in vprintf(), or whatever the base level function is the implements %f?

the fact that Arduino has sprintf() suggests that it is useful but that displaying floats, or more specifically doubles, was not considered essential.

sprintf() is more useful.

The c-string sprintf() is very fragile. You can easily overrun the buffer if you are not careful
Arduino Strings provides a constructor String(float,digs) that formats the float with that many digits.
My SafeString library (a detailed tutorial) provides Arduino print( ) support for printing directly to a SafeString, but unlike sprintf(), SafeStrings are protected against buffer overflows, will print an error msg and keep running.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.