Im having some problems with parsing gps coordinates with the arduino ide.

To be honest I want to process the data without a library.

From my sensor I get this String: 4815.98450

The result of String.toDouble(): 4815.9843750

I also parsed it on my own, but i got the same result: (yes this code is not nice ;))

char buf[10];
  msg.toCharArray(buf, 19);
  double num = 0.0;

  int c;

  c = buf[0] - '0';
  double num0 = (c * 1000);
  c = buf[1] - '0';
  double num1 = (c * 100);
  c = buf[2] - '0';
  double num2 = (c * 10);
  c = buf[3] - '0';
  double num3 = (c * 1);
  c = buf[5] - '0';
  double num5 = (c * 0.1);
  c = buf[6] - '0';
  double num6 = (c * 0.01);
  c = buf[7] - '0';
  double num7 = (c * 0.001);
  c = buf[8] - '0';
  double num8 = (c * 0.0001);
  c = buf[9] - '0';
  double num9 = (c * 0.00001);
  num = num + num0;
  num = num + num1;
  num = num + num2;
  num = num + num3;
  num = num + num5;
  num = num + num6;
  num = num + num7;
  num = num + num8;
  num = num + num9;

Does somebody have a solution for my problems?

Thank you very much :=)


There is no easy solution. The Arduino you are using does not support double precision floating point. The type double is just an alias for float, which has 24-bit accuracy.

Your program is actually giving you the correct result, as the float closest to 4815.98450 is exactly 4815.984375.

  • Thank you for your answer! You helped me a lot because now i know it is no bug. But now im searching for a workaround :) – Benjamin_Ellmer May 23 '20 at 8:32
  • @Benjamin_Ellmer: Maybe store the integer and fractional parts separately? – Edgar Bonet May 23 '20 at 8:40

double (or float) is just an inappropriate data type.

Perhaps you take int(4815) and float(0.98450) as two numbers?

And BTW, I bet from your sensor you don't get a String object.

  • Im reading the output from the TX of my sensor, so im pretty sure this is a string ;) i figured out that i can do my calculation without the first 2 digits of the number. there are some cases where it does not work but those cases are very unlikely – Benjamin_Ellmer May 24 '20 at 18:07

You can convert this to a long, do your arithmetic, and convert it back to an ASCII-Decimal number:

Remove the decimal point from the string. Convert the remaining string of digits to a long. Now you have the coordinate in binary, in units of the least significant decimal digit; 1 lsb == 0.00001, if you used 5 decimal places.

Manipulate your data however you need to using long integer arithmetic.

Divide the value by 10^ -(# of fraction digits you used). The quotient is the whole number part; the remainder is the fractional part. Print the quotient and a decimal point. Print the remainder padding with zeros to the left as necessary to result in your printing (# of fraction digits you used) total fraction digits.

The output conversion is even easier if you're willing to use sprintf():
Divide the value by 10^ -(# of fraction digits you used), as above. Let's assume 5 places as in your example:

char buffer[BIGENOUGH+1];
sprintf(buffer, "%ld.%05ld", value/100000, value%100000);

Note that I made two divisions to get the quotient and the remainder and assumed you could tolerate the performance hit. If you're expecting to crank out a lot of values and speed is a factor, you could look up or write a division routine that can return both the quotient and the remainder results from a single division.

Update: @edgar_bonet points out that the compiler is smart enough to notice this fragment uses both results of the numerically same division and avoids dividing twice after all.

  • Re the “routine that can return both the quotient and the remainder results from a single division”: this is exactly what avr-gcc does when compiling the example you provided. – Edgar Bonet May 23 '20 at 17:12

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.