How to obtain integer 15 from string "0.15"? function toFloat() gives 0.1499999

Hi dear,
I almost lost my mind when I figured out that this function doesn't work in my code.


Without string to float conversion, everything is fine.

float FL = 0.15;
FL = FL * 100;
int IN = FL;
Serial.print(FL);
Serial.print(" -> ");
Serial.println(IN);

Serial output:
15.00 -> 15


But when I want use toFloat(), then something is wrong.

String ST = "0.15";
float FL = ST.toFloat();
FL = FL * 100;
int IN = FL;
Serial.print(FL);
Serial.print(" -> ");
Serial.println(IN);

Serial output:
15.00 -> 14

It looks like in variable FL must be number (14.999999) when conversion to integer is (14). Serial monitor outputs 15.00 because rounding. But why is string "0.15" by .toFloat() converted to (0.1499999)?
I also noticed when input string is "0.14", then serial monitor output is "14.00 -> 14". In this case, output isn't rounded because function .toFloat() converts "0.14" to exactly (0.14) and not by 0.0000001 less as in case with "0.15".

This can be fixed by add two IFs before float to integer conversion:

String ST = "0.15";
float FL = ST.toFloat();
FL = FL * 100;

if (FL > 0) FL = FL + 0.01;
if (FL < 0) FL = FL - 0.01;

int IN = FL;
Serial.print(FL);
Serial.print(" -> ");
Serial.println(IN);

Serial output will be:
15.01 -> 15

This solution works for me, but I doubt that this is an optimal solution for every possible situation and has to be fixed maybe directly in function toFloat(). But I don't know where this function is located, or how to modify it properly. Can you help me with that? Or is it bug that has to be reported to developer of this function? I don't know how to report that either.

Best regards and have a nice day, Brano

Do not use the "String" object. You could do something like:

char str[] = "0.15";
char *token = strtok(str, "."); //token = "0"
token = strtok(NULL, "."); //token = "15"
int value = atoi(token); //Ascii TO Integer
Serial.println(value);

Thank you for super fast reply. But I can't use it because your solution doesn't work with negative numbers. I want integer -15 from string "-0.15".

Should be easy to test for a "-":

char str[] = "-0.15";
bool neg = (str[0] == '-');
char *token = strtok(str, "."); //token = "0"
token = strtok(NULL, "."); //token = "15"
int value = atoi(token); //Ascii TO Integer
if (neg) value = -value;
Serial.println(value);

Thank you. I red about not to use strings in arduino projects. I'm inexperienced programmer yet and therefore most of your code isn't familiar for me. I doesn't doubt that your solution is better than mine. And in near future I want to be familiar with your code. My first post isn't about to find another solution. It's about understanding behavior of toFloat() function. As you can see, I already have solution for my project. It's only about adding two lines of code. I wanted to understand toFloat().

I red about not to use strings in arduino projects.

Then you probably misunderstood.
You should avoid Strings in Arduino projects, particularly on the AVR platform.
(They're almost de regueur on the ESPs)

"floats" are single precision, that means that their value is "as close as it gets" with the limited memory they occupy. Also note that "string" and "String" are two different things.

You haven't read the documentation:

If you had, you would have read this:

"

Conversion from floating point to integer math results in truncation:

float x = 2.9; // A float type variable
int y = x; // 2

If, instead, you want to round off during the conversion process, you need to add 0.5:

float x = 2.9;
int y = x + 0.5; // 3

or use the round() function:

float x = 2.9;
int y = round(x); // 3

"