Float misunderstood

Hi!
I have some strange problem/misunderstanding with simple float numbers arithmetic. The following code snippet is printing some float variable f in the range from 0.00 to 4.00. The same variable is multiplied by 100 and printed as long type variable. The printed values are as expected till value of 2.40. The next number printed after 2.40 suprised me - it is 239 and than after 2.50 is 249 and so on... to the end.

void setup() {
  Serial.begin(9600);
  Serial.println("Hello");
}

void loop() {
  float f;
  long cc;
  
  //cc=value*100;
  for(f=0.00;f<4.00;f=f+0.10) {
    cc=f*100.00;
    Serial.println("---");
    Serial.println(f);
    Serial.println(cc);
    //ispisSegment(f);
    delay(500);
  }    
}

Can someone explain why is that happening - I suppose it is something related with floating point precision or something..., is there a way to correct this? Thanks a lot!!

tomcuga:
I suppose it is something related with floating point precision or something.

You have answered your own question.

As to correcting it, some Arduinos like the due have a double precision floating point variable type. Be warned though that many, such as the Uno, appear to have a double type, but just use float for it.

Another solution is to use int or long for your math, treating your variables as fixed point and just add a decimal point when you display them.

GolamMostafa:
The following codes does give 240 from 240.00 in my MEGA; but, the OP's sketch gives 239 from 240.00 in my MEGA -- why? It could be something with OP's for() loop where float addition is being done which is never precise?

Just run OP's code with printing sufficient significant digits (I used 8) and you can see what happens. Do the same for yours :wink:

GolamMostafa:
Thank you for your reply,
Yes, It works directly when you put an value to f, but try to increment variable f from for example 2.2 to 2.4 by 0.1 increment and that doesn't work - at least on my hardware - Arduino Nano.
I tried also with double type, and with 4 decimal places - the same thing
wildbill> Thank zyou for your reply, I'm using multiplication by 100 and adding an decimal point - and that works actually, but in the for loop it doesn't work - actually it works till 2.3 number.

These are the numbers

0.00000000	0
0.10000001	10
0.20000000	20
0.30000000	30
0.40000000	40
0.50000000	50
0.60000000	60
0.70000004	70
0.80000009	80
0.90000009	90
1.00000011	100
1.10000014	110
1.20000016	120
1.30000019	130
1.40000019	140
1.50000023	150
1.60000028	160
1.70000028	170
1.80000028	180
1.90000038	190
2.00000023	200
2.10000014	210
2.20000004	220
2.29999995	230
2.39999985	239
2.49999976	249
2.59999966	259
2.69999957	269
2.79999947	279
2.89999942	289
2.99999923	299
3.09999918	309
3.19999909	319
3.29999899	329
3.39999890	339
3.49999880	349
3.59999871	359
3.69999861	369
3.79999852	379
3.89999847	389
3.99999828	399

2.40000009	240

The last one is when one uses f=2.40; it's actually slightly bigger. Compare it with the result of the for-loop and you'll see that that one is slightly smaller.

Replace line 12 with:

cc=f*100.00 + 0.05;

Serial monitor:

Hello
---
0.00
0
---
0.10
10
---
0.20
20
---
0.30
30
---
0.40
40
---
0.50
50
---
0.60
60
---
0.70
70
---
0.80
80
---
0.90
90
---
1.00
100
---
1.10
110
---
1.20
120
---
1.30
130
---
1.40
140
---
1.50
150
---
1.60
160
---
1.70
170
---
1.80
180
---
1.90
190
---
2.00
200
---
2.10
210
---
2.20
220
---
2.30
230
---
2.40
240
---
2.50
250
---
2.60
260
---
2.70
270
---
2.80
280
---
2.90
290
---
3.00
300
---
3.10
310
---
3.20
320
---
3.30
330
---
3.40
340
---
3.50
350
---
3.60
360
---
3.70
370
---
3.80
380
---
3.90
390
---
4.00
400
---

JCA34F:
Replace line 12 with:

cc=f*100.00 + 0.05;

We are running after why the problem is there when the incremental value is 0.1. This example might help us to understand the problem.

GolamMostafa:
We are running after why the problem is there when the incremental value is 0.1.

Like @JCA34F already posted, it's a problem of the truncating conversion to an integral data type
and can be fixed by using rounding.
Usualy one would add .5 to the float to be converted, but here the values are so close,
that even a rounding to tenth works fine.

Thanks to all of you guys!! I learned something and that is great! In this exact situation I switched all my calculations to integer logic, actually long logic :slight_smile:
But it is good to know what the problem is!