I am broadcasting a fixed value float over a HC-12 radio which is then received by another HC-12 radio. I am then trying to convert that String to a Float which requires 6 decimal places. However, when I print the String value out and then the Float value out, I get two different answers.


    String lat=getValue(_msg, '|', 6); // Function to get lat value from incoming message
    Serial.println(lat.toFloat(), 6);

This then results in the following values being displayed to the user:


The value 51.507401 is the correct value, so I would ideally like the float value to be the same.

  • A float is only an approximation. That is as close as it can get. – Majenko Jul 12 '20 at 16:33
  • Is there anyway to get closer? Even .toDouble() gives the same result – William Smith Jul 12 '20 at 16:34
  • There is no double on an Arduino. It's all float. – Majenko Jul 12 '20 at 16:34
  • I would suggest not working in any form of floating point. Instead work in a fixed point. Use long and use the value x 1,000,000 or something like that. – Majenko Jul 12 '20 at 16:35
  • Store 51.507401 degrees as 51507401 microdegrees – Majenko Jul 12 '20 at 16:36

It seems the toFloat() method is being a bit sloppy in its conversion. The float closest to 51.507401 is 51.5074005126953125, which is only 0.13 ulps off. The number you got is the float right before it, namely 51.507396697998046875, which is 1.13 ulps off. Alas, the avr-libc functions atof() and strtod() make the same error.

I would suggest first considering whether the error is really significant for your application: it is only about 48 cm on the surface of the Earth. If this level of accuracy is relevant for you, then follow Majenko's suggestion and use an integer count of microdegrees.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.