Arduino Forum upgrade scheduled for Monday, October 20th, 11am-4pm (CEST). Sorry for the inconvenience!
Pages: [1]   Go Down
Author Topic: Floating point math issues....last significant digit not what I expected  (Read 565 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Sr. Member
****
Karma: 4
Posts: 289
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello!  Given the following code:

Code:
char latit[10] = {"4041.2358"};  //Degrees = 40, Minutes = 41, Seconds = 23.58
Serial.print("latit = ");
Serial.println(latit);

float flatit = atof(latit);
Serial.print("flatit = ");
Serial.println(flatit, 6);

flatit /= 100.00;
Serial.print("flatit = ");
Serial.println(flatit, 6);

float flatitdegrees = (int)flatit; //isolate degrees
float temp = (flatit - (int)flatit) * 100;
float fminutes = (int)(temp); //isolate minutes
float fseconds = (temp - fminutes) * 100; //isolate seconds

Serial.print("Degrees = ");
Serial.println(flatitdegrees);
Serial.print("Minutes = ");
Serial.println(fminutes,2);
Serial.print("Seconds = ");
Serial.println(fseconds, 2);

I get an output that looks like this:

Code:
latit = 4041.2358
flatit = 4041.235839
flatit = 40.412357
Degrees = 40.00
Minutes = 41.00
Seconds = 23.57

Can someone help me to understand what is going on with those last significant digits?
Logged

Arduino Uno;
Mega328

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 671
Posts: 51669
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A float has between 6 and 7 digits of precision. You string has 8. Converting it to a float does not produce and exact value, with 8 digits of precision.

Using Serial.print() to print more digits does not result in more precision, just more guesswork.

The results you are getting are exactly what I'd expect.
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 234
Posts: 14296
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

floating points are just not as precise as you want them to be.

The Arduino (UNO) uses IEEE-754 float format = 32 bits
1 bit for sign
23 bit for the fraction
8 bit for exponent (powers of 2)

the fraction part can only hold about 7 digits precision. YOur number has 8 so it is rounded to the nearest number it can represent.

Details see Wikipedia - http://en.wikipedia.org/wiki/IEEE_754-1985 -
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

0
Offline Offline
Sr. Member
****
Karma: 4
Posts: 289
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks everyone for the great explanations.  Quick and easy fix in my code was to separate the digits before and after the decimal using the decimal as the delimiter and then working the math on each section individually.  Works perfect now!
Logged

Arduino Uno;
Mega328

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Floating point math issues....last significant digit not what I expected

It would have been a miracle if t he last significant digit were what you expected. That's the nature of floating point math.
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 234
Posts: 14296
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
That's the nature of floating point math.
And we haven't even discussed error propagation due to math operators
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Pages: [1]   Go Up
Arduino Forum upgrade scheduled for Monday, October 20th, 11am-4pm (CEST). Sorry for the inconvenience!
Jump to: