A cheap trick to round a number to one decimal place (in "chop-off mode") is to multiply it by 10, convert it to an integer, and divide by 10.0f
again:
float myVal = 123.89f;
myVal = (long)(myVal * 10) / 10.0f;
// = ((long)1238.9) / 10.0f
// = 1238 / 10.0f
// = 123.8
You can then print this modified number to the serial monitor.
This method can also be generalized to other precisions. For 2 decimal places, we just have to multiply by 10^2 (100) and divide by 10^2. A macro would be:
#define TRUNCATE(val, numDecimalPlaces) \
(float)(((long)((double)(val) * pow(10, (numDecimalPlaces) * 1.0f))) / (pow(10, (numDecimalPlaces)* 1.0f)))
Note: You don't have to actually dynamically compute pow(10, numDecimalPlaces)
, you can also create macros for each decimal precision from 1 to x
and simply precompute that value (100, 1000, 10000, ..).
The same can also be achieved by using the standard library function trunc
from math.h
:
#define TRUNCATE_TO_ONE(val) \
(trunc((val) * 10.0f) / 10.0f)
See http://www.cplusplus.com/reference/cmath/trunc/.
Here's a small sketch in which it is demonstrated:
#include <Arduino.h>
#define TRUNCATE(val, numDecimalPlaces) \
(float)(((long)((double)(val) * pow(10, (numDecimalPlaces) * 1.0f))) / (pow(10, (numDecimalPlaces)* 1.0f)))
#define TRUNCATE_TO_ONE(val) \
(trunc((val) * 10.0f) / 10.0f)
void printValueFormatted(float value, int numDecimalPlaces) {
//format correctly
char buf[20];
char* res = dtostrf(value, sizeof(buf)-1, numDecimalPlaces, buf);
//skip over empty chars
while(*res == ' ')
res++;
//print buffer
Serial.println(res);
}
void setup(void)
{
Serial.begin(115200);
}
void loop(void)
{
float myVal = 123.8978f;
printValueFormatted(myVal, 4);
printValueFormatted(TRUNCATE(myVal, 1), 1);
printValueFormatted(TRUNCATE(myVal, 2), 2);
printValueFormatted(TRUNCATE(myVal, 3), 3);
printValueFormatted(TRUNCATE(myVal, 1), 4);
printValueFormatted(TRUNCATE(myVal, 2), 4);
printValueFormatted(TRUNCATE(myVal, 3), 4);
delay(1000);
}
Prints
123.8978
123.8
123.89
123.897
123.8000
123.8900
123.8970
double
instead of afloat
. But it's also unclear that the value being printed is not already the most accurate decimal approximation of the value internally stored. Without your code this is unanswerable.float x = 23.40;
, the compiler rounds that number to the nearest representable float, which happens to have the exact value 23.3999996185302734375. If you truncate this to one decimal place, then23.40
ends up being printed as “23.3”!