0

I'm reading from a temperature sensor. I get float values with 2 decimals. I want to round them to nearest 0.1.

This is my sketch:

void setup() {
  Serial.begin(115200);
}

void loop() {
  float temperature = 21.81;
  float rounded_temperature = round(temperature * 10) / 10.0;
  Serial.print("21.81 ->");
  Serial.println(rounded_temperature);
  delay(1000);

  temperature = 21.79;
  rounded_temperature = round(temperature * 10) / 10.0;
  Serial.print("21.79 ->");
  Serial.println(rounded_temperature);
  delay(1000);

  temperature = 21.77;
  rounded_temperature = round(temperature * 10) / 10.0;
  Serial.print("21.77 ->");
  Serial.println(rounded_temperature);
  delay(1000);

  temperature = 21.70;
  rounded_temperature = round(temperature * 10) / 10.0;
  Serial.print("21.70 ->");
  Serial.println(rounded_temperature);
  delay(1000);
}

This is the output:

21.81 ->21.85
21.79 ->21.75
21.77 ->21.75
21.70 ->21.75

And this is the output I would... Rounded to "0" and not "5".

21.81 ->21.80
21.79 ->21.80
21.77 ->21.80
21.70 ->21.70
3
  • temperature could be also negative
    – sineverba
    Dec 30 '20 at 11:18
  • this is not an arduino question ... it is a general programming question
    – jsotola
    Dec 30 '20 at 11:30
  • 1
    @jsotola OP is using the round function, which is part of the Arduino library.
    – Gerben
    Dec 30 '20 at 15:49
3

Using roundf() function:

float rounded_temperature = roundf(temperature * 10) / 10;

1

float variables do not have a number of decimal places. They are merely an approximation anyway. Instead it's when you print that you decide how many decimals to display.

Serial.println(temperature, 1); // Print with 1 decimal place

Or to put it into a string:

char buf[8]; // Room for 7 characters plus NULL terminator
float val=23.81;

dtostrf(val, -7, 1, buf); // 7 characters with 1 decimal place and left aligned (negative width)
4
  • mmm... My trouble is that I send that data via MQTT to HomeAssistant. I want to send them as "my format" and not with the .50
    – sineverba
    Dec 30 '20 at 11:09
  • Then format it into a string and send that. Use dtostrf to format a char[].
    – Majenko
    Dec 30 '20 at 11:14
  • Isn't there a native function to round to .x0 instead of .50 ?
    – sineverba
    Dec 30 '20 at 11:20
  • @sineverba Even if you do "round" the float chances are it won't be rounded. Like I said - floats are only an approximation. The only way to fix it to a specific number of digits is to change it to a different format - such as text. With dtostrf().
    – Majenko
    Dec 30 '20 at 11:32
1

I often store the floating point data that I get from a sensor in integer to preserve the decimal precision that I want by multiple it by 10 before casting it into an integer. It is easier and more efficient (compare to string or float) to send over to another system. This is also how many sensors representing and store the floating data (e.g. TMP275) as well.

To achieve what you want, here is what I would do:

#include <math.h>

void setup() {
  Serial.begin(115200);

  float i=21.81;
  float j=21.79;
  float k=21.77;
  float p=21.70;

  // convert to integers
  int l = (int) round(i*10);  // 218
  int m = (int) round(j*10);  // 218
  int n = (int) round(k*10);  // 218
  int o = (int) round(p*10);  // 217

  // Convert back to actual floating point for display
  Serial.println((float)l/10);  //21.80
  Serial.println((float)m/10);  //21.80
  Serial.println((float)n/10);  //21.80
  Serial.println((float)o/10);  //21.70
}
2
  • Ok.... but 21.81 rounded is 21.80, not 21.90...
    – sineverba
    Dec 30 '20 at 12:58
  • 2
    I change it to use round() instead of ceil().
    – hcheung
    Dec 30 '20 at 13:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.