small problem with float

okk here is the problem : my project mesures distance between 2 points with gps and xbee , so far im able to collect the latitude and longtitude for the points in 4 variable , but the the coordinates that im getting from the gps changes rapidly after 3 points in both long and lat and that effects the result so badly. so what i need is to get numbers in this format for example :

lat1 : 32.11 , lon1 : 34.8717
lat2 : 32.11 , lon2 : 34.8716

Or better yet, make a function macro to round any number to any decimal point. Put this at the top of your sketch:

#define roundTo(a,b) round(a*(1/b))/(1/b)

Here are some examples:

float num1 = roundTo(34.789854, 0.01); //returns 34.79
byte num2 = roundTo(34.789854, 10); //returns 30
float num3 = roundTo(34.789854, 0.1); //returns 34.8

If you want to drop the extra numbers instead of rounding them, change round to floor.

noooo i can't round at all every number is extreemly important for distance calculations .

If you want to get a more "stable" value, you can get a whole bunch of readings, and average them.

how it can be done ?

Hi louish

I think you are doing it wrong - you should keep the high resolution numbers as long as possible.

Recalculate the distance even if the responce from the gps is noisy and then you should decide if the new distance has changed enough -or you could make a running average.

-Fletcher

Look at the Smoothing example, and use floats or doubles instead of ints.

I wouldn't bother with doubles; they're overrated on the Arduino :wink:

Double == float on arduino.

i don't think smoothing is the solution for my problem because the gps transmitting NEMA protocol via serial communication in pin 2,3 . from the protocol im only interested in position and i've no way to get the position exept using this command : gps.f_get_position(&lat11, &lon11);
and this comand doesn't give me any choice to control the numbers i get so im storing the data in deferent variables to get the numbers as i want and its not workinig so far /]

What do you think the solution might be?
You don't really say what the problem is.

all i want is to get number from this command : gps.f_get_position(&lat1, &lon1);
in this format :
lat1 = 32.11
lat2=34.78755
so i can use them with this command : gps.distance_between (lat1,lon1,lat2,lon2);
if i send lat1 and lon1 as they come out from :gps.f_get_position(&lat1, &lon1);
i get wrong answer but if i send them as shown above it works

A variation of 0.01 equates to approx half a mile.
So, +/- this on two readings could be a mile out! :slight_smile:

What target accuracy are you trying to achieve?

yes i know i want the latitude to be 2 points after the decimal and longititude to be 4 points after the decimal for example :

lat = 32.12
lon=34.1234
im trying to dig in the headers and cpp files of tiny gps library to change the way: gps.f_get_position(&lat1, &lon1);
return numbers but with no luck untill now .

IEEE floating point has that problem, like when you should have 1.0 but you get .999999.

If you can find the way, do your work using fixed-point with unsigned longs or long longs and the digits won't shift. Even signed longs will give you a solid 9 places.

GoForSmoke is right. Floating point representation in computers is largely approximate because of the way that the numbers are represented. If you want accuracy you should long integers (for example 32.11 can be 3211). As long as all the number are scaled up the same way (eg, by 100 in this case) then you are all correct and at the end you just insert the decimal in the right place if you need to.

i get wrong answer but if i send them as shown above it works

Give an example of the returned lat and long and the wrong answer. And then show why what you want to do with the numbers is an improvement.

Pete

for example :
lat1=32.11 lon1=34.8780
lat2=32.11 lon2=34.8781

the distance is 9.4m
now i have lat1 and lon1 stored in the memory so i don't care about them . but to get lat2 and lon2 i need this function :
gps.f_get_position(&lat2, &lon2);
but this function keeps changing the coordinates all the time and any change in any digit is abig problem so i need to force this function to give the number as i want (2 digits . 4 digits) only ... this is how i done that with no sucess :

gps.f_get_position(&lat11, &lon11);
char buf2[30],buf3[5];
 dtostrf(lon11, 2, 3, buf3);
 float lon1= atof(buf3);
g=gps.distance_between (lat1,lon1,lat22,lon22);

louish:
to get lat2 and lon2 i need this function :
gps.f_get_position(&lat2, &lon2);
but this function keeps changing the coordinates all the time and any change in any digit is abig problem so i need to force this function to give the number as i want (2 digits . 4 digits) only

Is your GPS giving credible values for lat and long? To what resolution are they accurate? Since the float data type will be capable of holding numbers with more precision than the accuracy of your GPS, the least significant digits will be affectively noise. You could ignore these since they won't affect the accuracy of your calculation - the result you get will have more digits than are accurate and you will have to round or ignore the extra digits in any case, so there is no significant benefit to also doing that rounding/truncation to the input figures.

On the other hand, if the input figures from your GPS are varying wildly, maybe that is the root of your problem. If you're getting garbage in, everything else you calculate will also be garbage.

Peter, I think that the GPS data being stuffed into 32-bit floats is one source of error.

gps.f_get_position(&lat11, &lon11);
char buf2[30],buf3[5];
 dtostrf(lon11, 2, 3, buf3);
 float lon1= atof(buf3);
g=gps.distance_between (lat1,lon1,lat22,lon22);

Does dtostrf() as you use it do rounding, as in rounding up or down?

You could try converting the float to a string with more places than you need then placing a terminating zero after the last place you need, but with floats it may help repeatability while losing actual accuracy. In the very act of cutting off digits to get consistent results, the results will be consistently wrong.

Anyway here is how that would work. I have a C string buf[12] with a number in it.
text -- ASCII hex:
1.2345678 -- 31 2E 32 33 34 35 36 37 38 00 00 00
I cut off everything past the 4th decimal place:
1.2345 -- 31 2E 32 33 34 35 00 37 38 00 00 00

However when I convert that back into a float I don't expect it to equal 1.2345 but something close. I'm sure it works better with 64-bit floating point.