rounding or truncating float

Before making this topic I read almost all examples and suggestions from this forum. Im just beginner so please dont throw stones on me :-).

I am getting stream via serial to arduino, stream is coming from other arduino as ascii chars. Around 140 chars per request.

I need to round and truncate floats to 2 decimal points then compare with other floats which have 2 decimal precision.

Stream is copied into String first then manipulations are done sorting values.

String a=1.1234567e-02; float B=a.toFloat(); //now is 0.0123456

float c=b*10000.0; int d=(int)c; float e=(float)d/10000.0

So how to get rid of digits after 2 dec point? I.e. Should be 0.01.

I can convert it back to string then truncate digits after 2 dec points and convert back to float. But is there an easy way to do this?

Don't use floats in the first place. Multiply the values by 100 and use ints instead for calculations and comparisons. Display as a float with 2 decimal places if required.

Certainly avoid Strings if at all possible.

If you are planning to round and compare for equality, that is not a good idea. Rather, you should implement a bracket with the +/- limits of the target number:

if (sourceNum > targetNum-limit && sourceNum < targetNum+limit) {...}

edit … if you must use floats

Why mess with float if you want a int which is wayyyyyyyyyyyyyyyyyyyyyy faster? So I agree fully with UKHeliBob. And don't mess around with making it a String again, once is already terrible enough.

If you just want 0,01, why not simply not load more then two digits after the decimal into the float? And to do it with normal C strings instead of String you can just use atof().

UKHeliBob: Don't use floats in the first place. Multiply the values by 100 and use ints instead for calculations and comparisons. Display as a float with 2 decimal places if required.

Certainly avoid Strings if at all possible.

How I can convert ascii to int same time determining right exponental value? I.e. If ascii is 1.1234567e-01 how int will round it right? I tried before converting directly to int but was getting wrong results especially with exponents. Im not displaying that numbers on the screen I must compare rounded number with number in database.

surepic: How I can convert ascii to int same time determining right exponental value? I.e. If ascii is 1.1234567e-01 how int will round it right? I tried before converting directly to int but was getting wrong results especially with exponents. Im not displaying that numbers on the screen I must compare rounded number with number in database.

Read a float and then cast it to an int after scaling. 1.1234567e-01 * 100 = 11.234567 which will be truncated to 11.

You then compare it with 11 in the database.

aarg:
If you are planning to round and compare for equality, that is not a good idea. Rather, you should implement a bracket with the +/- limits of the target number:

if (sourceNum > targetNum-limit && sourceNum < targetNum+limit) {...}

edit … if you must use floats

I have numbers in database lets say.
A=0.01
B=0.02
C=5.68
Etc

And lot of cases with different values for a b and c. So data must be compared against all that values then some statement must be done.
I could understand how I can put targetnum cos targetnum is database numbers which are more than 500. I.e. 500 different cases and 500 different statements.

Thanks for help.

Or do the multiplication with 1000 before even making it an int by moving the dot. Can be pretty efficient but bit harder to do if you want to make it safe for all number.

In database numbers are floats or numbers with 2 decimal places i.e. 1.12

First need rounding 1.123489=1.12349=1.11235 Then need truncating to 2 dec places 1.11235=1.11

Need rounding for debugging purposes if somethibg will go wrong.

surepic: I have numbers in database lets say. A=0.01 B=0.02 C=5.68 Etc

And lot of cases with different values for a b and c. So data must be compared against all that values then some statement must be done. I could understand how I can put targetnum cos targetnum is database numbers which are more than 500. I.e. 500 different cases and 500 different statements.

Thanks for help.

A switch statement with 500 cases is way too much. You should design some kind of looping construct to handle it.

surepic: In database numbers are floats or numbers with 2 decimal places i.e. 1.12

First need rounding 1.123489=1.12349=1.11235 Then need truncating to 2 dec places 1.11235=1.11

Need rounding for debugging purposes if somethibg will go wrong.

We answered all that for you.

septillion: Or do the multiplication with 1000 before even making it an int by moving the dot. Can be pretty efficient but bit harder to do if you want to make it safe for all number.

In my first post I am multiplying float to 10000.0 before making int to shift the point to the right.

But then dont know how to truncate without using strings. In string I can do manipulations with just deleting numbers up to 2 dec places knowing beforehand precision of float is 7 dec pl then can delete 7-5 chars. But this everythibg is using way too much space.

An implicit cast will truncate:

float PI = 3.14;
int almostPI = PI;

almostPI will be assigned 3.

One of the methods that I just figured out is working and is easy to understand:

float b=7.4410148e-04 // which is 0.00074410148 float c=1.7973011e-02 // which is 0.017973011

float a = roundf(b*100.0)/100.0; // will round to 2 decimal places i.e. 0.00 float a = roundf(c*100.0)/100.0; // will round to 2 decimal places i.e. 0.02 which is nearest to 0.017(i.e. round up)

Which is pretty heavy calculations for a Arduino... Why do you receive (ASCII) floats? Can't you just get integers?

I cant cos im writing client side of the project. Server side sends same data to pc program as well which is dealing with ascii floats and needs exponent in calculations.

Alright, so if you really can’t control the incoming stream then:

a) Write a parser that can parse the ASCII float representation directly into a int. (With or without rounding…) So
char “1.1234567e-02” => int 1, or
char “12.453431” => int 1245

b)Or at least get rid of the float as fast as you can and use integers in your program. Aka,
char “1.1234567e-02” => float 1.1234567e-02 => float 1.1234567 => int 1, or
char “12.453431” => float 12.453431 => float 1245.3431=> int 1245

What is so difficult about the suggestion in reply #2? It requires no conversion of float to anything else and you could code the comparison expression as a macro. If you handle your database entries as an array instead of a 500 case switch statement, you wouldn't even need the macro as you would only use the line once.

septillion: Alright, so if you really can't control the incoming stream then:

a) Write a parser that can parse the ASCII float representation directly into a int. (With or without rounding...) So char[] "1.1234567e-02" => int 1, or char[] "12.453431" => int 1245

b)Or at least get rid of the float as fast as you can and use integers in your program. Aka, char[] "1.1234567e-02" => float 1.1234567e-02 => float 1.1234567 => int 1, or char[] "12.453431" => float 12.453431 => float 1245.3431=> int 1245

How I will compare int with float in database? It must be either string or char array with 2 dec number representation in it or float with 2 decimals. Cant get how comparing int with float will be easy to implement. Cos even float 0.00 != 0.000 in arduino.

To aarg: Yes example in post #2 looks will work for me thanks and suggestion about 500 cases too.

Thanks everybody for all suggestions!