toFloat() issue

I have seen the other post/thread about the precision of float and use of the toFloat() string function.

I am using toFloat() to convert a floating point number sent in a string as part of a cloud function like this:

int remoteParam(String command)
    if      (command.startsWith("mxc"))
        String pvalue = command.substring(3);
        double i = pvalue.toFloat();
        value = i;
        if (i < 0.06 || i > 0.5) return -1;     // request OK but value out of valid range 
        return 1;                               // request and value OK
        return -99;                             // request not recognised/supported

value is declared as a float. I have tried declaring i as float and double and this makes no difference.

If I send : particle call deviceID Remote_Param “mxc0.06” this returns -1 rather than 1. If I print out value in the loop it shows as 0.060000. If I send : particle call deviceID Remote_Param “mxc0.060001” this returns 1 and the value prints as 0.060001. Can anyone help explain this? Surely this value is well within the accuracy (decimal points) of float? And suggest a solution.

You need to understand how floating point numbers are stored in binary form.

The printed representation of floats is not enough to look at. Some numbers are imposible to represent exactly as float or double (e.g. 1/3).
If you have a number 0.0599999999999999999999999999999987 but only have 10 or 20 places to display you will see 0.06000000000000000000 but it’s still <0.06.

If you want a precise boundary check against constants you need to carefully select the boundaries. But better is a more fuzzy logic that won’t break just by the flip of a single bit at some position with measly significance.

1 Like

I will again plug this excellent online calculator for 32-bit floats:

When I enter 0.06, the nearest 32-bit float is actually 0.0599999986588954925537109375 while the next number up (one ULP) is 0.060000002384185791015625 so it depends on how you do rounding as to which one you get. It is possible that the compiler handles 0.06 differently than the toFloat() method.

Printing the numbers in hex is a good way to see if they are different.

1 Like

@bko and @ScruffR, thanks both for your replies - just the precision of storing a float in 32 bits!