Go Down

Topic: string manipulation and float math problems (Read 1 time) previous topic - next topic

jerseyguy1996

In this piece of code:

Code: [Select]
float f, latminutes, longminutes;
    long latdecCoords, longdecCoords;
    int latdegrees, longdegrees;
   
    //char sLongDecCoords[10], sLatDecCoords[10];
   
    //convert latitude to GPS Decimal format
    f = atof(latit1);
    f /= 100.00;
    latdegrees = (int)f; //isolate degrees
    latminutes = ((f - (int)f) * 100.0)+(atof(latit2)/10000.00); //get minutes and fraction of minutes
    latdecCoords = (long)((latminutes / 60.0)*1000000);  //convert to fractions of a degree
    //latdegrees += latdecCoords;  //combine it all into one float
   
    if(NS[0] == 'S') latdegrees *= -1.0;
   
    //cconvert longitude to GPS decimal format
    f = atof(longit1);
    f /= 100.00;
    longdegrees = (int)f; //isolate degrees
    longminutes = ((f - (int)f) * 100.0) + (atof(longit2)/10000.00);
    longdecCoords = long((longminutes / 60.0)*1000000);
    //longdegrees += longdecCoords;
    if(EW[0] == 'W') longdegrees *= -1.0;
   
   
   
    sprintf(latitude, "%i.%ld", latdegrees, latdecCoords);
    sprintf(longitude, "%i.%ld", longdegrees, longdecCoords);
    Serial.print(longit2);
    Serial.print(",");
    Serial.print(atof(longit2)/10000, 4);
    Serial.print(",");
    Serial.print(latdegrees);
    Serial.print(",");
    Serial.print(latminutes,4);
    Serial.print(",");
    Serial.print(longdegrees);
    Serial.print(",");
    Serial.println(longminutes,4);


and

Code: [Select]
latit1 is equal to "4041"
latit2 is equal to "1271"
longit1 is equal to "07406"
longit2 is equal to "4956"


I get an output that looks like this:

Code: [Select]
4956,0.4956,40,41.1271,-74,6.4954


The problem is longit2.  It is equal to "4956" but for some reason after doing this to it:

Code: [Select]
longminutes = ((f - (int)f) * 100.0) + (atof(longit2)/10000.00);

the decimal piece ends up being .4954, and this is repeatable.....it is always .0002 off from the expected value.  I progressively printed out an evaluation of that statement and it maintains the correct value until I add the arguments in front of the plus sign.  What could be going wrong with this?  The calculation for latitude works fine....just the longitude is the problem.
Arduino Uno;
Mega328

PaulS

1000000 doesn't look much like an int. 1000000UL does, on the other hand, look like an unsigned long.

http://snippets-r-us.com might be able to help you. We can't verify that latit1, latit2, longit1, and longit2 are what you say they are (properly NULL terminated arrays of chars).

Intermediate variables, and Serial.print() statements, might help.

jerseyguy1996

Well I figured out where the problem is but I am not sure how to fix it.  To be honest, for this application this level of precision is ridiculous but it still just bugs me that it is coming out like this.  Basically, these two lines:

Code: [Select]
f = atof(longit1);
    Serial.println(f, 4);


result in the output:

Code: [Select]
7406.0000


and

Code: [Select]
f /= 100.00;
    longdegrees = (int)f; //isolate degrees
Serial.println(longdegrees);


results in

Code: [Select]
74

and

Code: [Select]
longminutes = ((f - (int)f) * 100.0);
Serial.println(longminutes,4);


results in

Code: [Select]
5.9998

which is wrong.....it should be 6.0000 based on the original value of f being 7406.0000.

Does anyone know why it may be losing .0002 on that value?  I don't think I am overrunning any of my datatypes.
Arduino Uno;
Mega328

PaulS

Quote
which is wrong.....it should be 6.0000

No. You are performing floating point arithmetic. The 5.9998 value is perfectly reasonable.

Print out f to 6 decimal places, after you divide it by 100.0, to see that.

KeithRB

"Working with floating point is like moving piles of sand. Every time you move one you lose a little sand and pick up a little dirt."

Go Up