Math.round in Arduino

Hi,

I am trying to convert a float to an int and round up/down as necessary.

This works to convert to an int.

#include <Math.h>

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

void loop() {

float z = 78.923;
int a = (int) z;
Serial.println(z);
Serial.println(a);
Serial.println();
delay(2000);
}

However I can't get the Math.round function to work.

#include <Math.h>

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

void loop() {

float z = 78.923;
// int a = (int) z;
int a = (int) Math.round (z);
Serial.println(z);
Serial.println(a);
Serial.println();
delay(2000);
}

This give me an error "'Math' was not declared in this scope"

can anyone tell me what I am doing wrong?

Please use code tags when posting code! It's the # symbol next to the typewriter in the editor.

Your problem is case sensitivity. It should be

#include <math.h>

and of course

var2 = round(var1);

I changed the code like this:

#include <math.h>

int a;
int b;

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

void loop() {
float z = 78.923;
a = (int) z;
b = round(a);
Serial.print("z = ");
Serial.println(z);
Serial.print("a = ");
Serial.println(a);
Serial.print("b = ");
Serial.println(b);
Serial.println();

But the result is:

z = 78.92
a = 78
b = 78

The round functions is not working.

Round (a);
?
Math function not working, or test method not working? :wink:

If you want to round a float to the nearest whole number, just add 0.5 and cast to the appropriate integer type. Decide how you want to deal with -ve values, if you expect any. In some situations you want to always round downwards, in other situations it's appropriate to round towards zero. If you're doing anything statistical with the results, that distinction is important.

Round is working correctly, but you are doing round((int)78.923), which is 78.

madworm:
Please use code tags when posting code! It's the # symbol next to the typewriter in the editor.

You were already asked once and ignored it. When posting code, please wrap them in code tags.

Babak1:
I changed the code like this:
The round functions is not working.

Your code works exactly as you wrote it. See below

Babak1:

   float z = 78.923;   // z contains 78.923

a = (int) z;          // a now contains 78
  b = round(a);      // b = round(78) = 78

You want:

 b = round(z);
1 Like

Thank you for all your help, I have it working now. :slight_smile:

void setup() {
float a = 7.49;
float b = 7.50;
int y = (int(a100)+50)/100;
int z = (int(b
100)+50)/100;
Serial.begin(9600);
Serial.print(a);
Serial.print(" to ");
Serial.println(y);
Serial.print(b);
Serial.print(" to ");
Serial.println(z);
}

void loop(){}

For the next person Googling this, here is the better answer

float a = 27.1;
float b = 27.9;

int round_a;
int round_b;

round_a = int( a + 0.5);
round_b = int( b + 0.5);

After the above runs round_a==27 and round_b==28.

The above is fast and does not need to use any library functions. In always works because the int() cast truncates (aka "rounds down").

Notice that (int(a*100)+50)/100 is the same as int(a+0.5) but one is simpler

3 Likes

chrisalbertson:
For the next person Googling this, here is the better answer

You don't need the 'int()'. This works just fine:

round_a = a + 0.5;
round_b = b + 0.5;

OK, Chris, now what happens if you use negative numbers? Your code gets the wrong answer for negatives.

Usually it is a mistake to try to re-write library functions. The library has been tested for "unusual" conditions such as negative numbers. There's a whole bunch of other boundary conditions, particularly with floats.

The library has also been tested for speed. The deep-down library code which is actually included by the compiler is not the code you see in the textbook. This code may have been optimised for the specific processor you are working on, using all of the special instructions available to that processor. If you change the Arduino board in the IDE and re-compile, it takes a lot longer because it's now compiling different libraries specific to that new processor.

In the general case, you are never going to be able to write code faster than the library. In specific cases, such as if you had defined round_a and round_b to be unsigned ints then maybe your code is faster but I would still bet on the library.

1 Like

(deleted)

While this topic is a bit old, there appears to be some misunderstanding on the ability to "round to n-digits after decimal point".

In IEEE floating-point format (and most non-IEEE formats as well) normalized values are stored as 1.bbbbbb * 2^exponent. The 'bbbbbb' is referred to as the mantissa.

Except for de-normalized numbers, the mantissa always represents a sum of fractional powers of 2, i.e. 1/2, 1/4, 1/8, 1/16, 1/32, ....

The exponent is an "offset" signed integer where 0...max in the exponent field represents about -max/2...0...max/2

The result of this powers-of-2 format is you cannot divide by powers of 10 and retain exact decimal accuracy for most numbers.

It is easy to multiply by 10 using powers of 2: 10x == x * (8 + 2)

It is NOT easy to divide by 10 using powers of 2:

-- 1/8 is too big. 1/16 is too small.

-- 2 * 1/16 is the same as 1/8, so that doesn't work.

-- 1/16 + 1/32 is too small.

-- 1/16 + 1/32 + 1/64 is too big.

-- 1/16 + 1/32 + 1/128 is too big.

-- 1/16 + 1/32 + 1/256 is too small.

-- 1/16 + 1/32 + 1/256 + 1/512 is too small.

Eventually you realize you have an infinite repeating sequence of bits representing ever-smaller powers of two:

000110011001100110011...

which represents

2-4+2-5+2-8+2-9+2-12+2-13+2-16+2-17+2-20+2-21...

So it is impossible to represent 1/10 in a finite-length set of binary fractions.

While it is trivial to write things like round(x * 1000) / 1000 and think that you have managed to get an answer accurate to precisely 3 decimal digits, in reality you are fooling yourself.

In order to actually get a precise number of digits after a decimal point, you MUST EITHER use a math package supporting a decimal-based number system -- e.g. binary-coded-decimal -- OR use a fixed-point system where everything is stored as integers which are assumed to represent K * 10^n, where n is the number of decimals after the decimal point. For 2 digits precision, everything is stored as *100 values. For 3 digits precision, everything is stored as *1000 values.

Any other approach to "round to n digits after decimal point" will fail to maintain desired accuracy for most real decimal numbers.

2 Likes