high precision conversion troubles

C

cerr

Hi There,

I need to do some calculations with GPS coordinates and i get all
weird values and i can't see where i'm going wrong.
My code:
Code:
            // calculate the average xy coordinates out of the
polygon's corner points
            double CinXAvg =((((sphericalpolygon *) curApproach-[QUOTE]
getCheckInPolygon())->getCornerPoints()->at(0).x +[/QUOTE]
                                  ((sphericalpolygon *) curApproach-[QUOTE]
getCheckInPolygon())->getCornerPoints()->at(1).x +[/QUOTE]
                                  ((sphericalpolygon *) curApproach-[QUOTE]
getCheckInPolygon())->getCornerPoints()->at(2).x +[/QUOTE]
                                  ((sphericalpolygon *) curApproach-[QUOTE]
getCheckInPolygon())->getCornerPoints()->at(3).x)*10000000)/4;[/QUOTE]

            double CinYAvg =((((sphericalpolygon *) curApproach-[QUOTE]
getCheckInPolygon())->getCornerPoints()->at(0).y +[/QUOTE]
                                  ((sphericalpolygon *) curApproach-[QUOTE]
getCheckInPolygon())->getCornerPoints()->at(1).y +[/QUOTE]
                                  ((sphericalpolygon *) curApproach-[QUOTE]
getCheckInPolygon())->getCornerPoints()->at(2).y +[/QUOTE]
                                  ((sphericalpolygon *) curApproach-[QUOTE]
getCheckInPolygon())->getCornerPoints()->at(3).y)*10000000)/4;[/QUOTE]
            //save the average value in a hash table so we can later
go ahead and find the outest polygons
            xy AvgCIN(static_cast<double>(CinXAvg/10000000),
static_cast<double>(CinYAvg/10000000));
            AvgHashTable[AvgHashTable.size()]=AvgCIN;
        }

    }
    for (int i=0; i < AvgHashTable.size(); i++) {
        if (i==0) {
            TopLeft.x=AvgHashTable[i].x;
            TopLeft.y=AvgHashTable[i].y;
            BottomRight.x=AvgHashTable[i].x;
            BottomRight.y=AvgHashTable[i].y;
        }
        else {
           if (AvgHashTable[i].x < TopLeft.x)
               TopLeft.x=AvgHashTable[i].x;
           if (AvgHashTable[i].y < TopLeft.y)
               TopLeft.y=AvgHashTable[i].y;
           if (AvgHashTable[i].x > BottomRight.x)
               BottomRight.x=AvgHashTable[i].x;
           if (AvgHashTable[i].y > BottomRight.y)
               BottomRight.y=AvgHashTable[i].y;
       }
    }
The explanation the first lines are GPS coordinates from a polygon and
i take the average from the 4 points to figure out the centre of the
polygon (I know, geometrically it's not 100% correct but I figured
this should be good enough for me/my polygons) anyways I multiply it
by 10,000,000 in order to get rid of the digits pst the decimal point.
Then after the division by 4 i get two decimal places back....
then i add the numbers to a map in order to be able to easily access
them. type xy is a class with two double variables, x and y. This is
how my globals are declared:
map<int, xy>AvgHashTable;
xy TopLeft;
xy BottomRight;
Then i wanna loop through all the elements and figure out the largest
and the smallest value...
somewhere my double values get screwed and i have all weird numbers in
BottomRight as well as in TopLeft

Now my source values are all in the format with 7 decimal numbers. And
in the end I have in TopLeft.x 49.213812599999997 and in BottomRight.x
I got 49.281173000000003... The y values look good for both... any
ideas why these numbers look so awkwardly?

Thanks,
Ron
 
V

Vladyslav Lazarenko

Hi There,

I need to do some calculations with GPS coordinates and i get all
weird values and i can't see where i'm going wrong.
My code:
Code:
            // calculate the average xy coordinates out of the
polygon's corner points
            double CinXAvg =((((sphericalpolygon *) curApproach->getCheckInPolygon())->getCornerPoints()->at(0).x +

                                  ((sphericalpolygon *) curApproach->getCheckInPolygon())->getCornerPoints()->at(1).x +

                                  ((sphericalpolygon *) curApproach->getCheckInPolygon())->getCornerPoints()->at(2).x +

                                  ((sphericalpolygon *) curApproach-
[QUOTE]
getCheckInPolygon())->getCornerPoints()->at(3).x)*10000000)/4;[/QUOTE]

            double CinYAvg =((((sphericalpolygon *) curApproach->getCheckInPolygon())->getCornerPoints()->at(0).y +

                                  ((sphericalpolygon *) curApproach->getCheckInPolygon())->getCornerPoints()->at(1).y +

                                  ((sphericalpolygon *) curApproach->getCheckInPolygon())->getCornerPoints()->at(2).y +

                                  ((sphericalpolygon *) curApproach->getCheckInPolygon())->getCornerPoints()->at(3).y)*10000000)/4;

            //save the average value in a hash table so we can later
go ahead and find the outest polygons
            xy AvgCIN(static_cast<double>(CinXAvg/10000000),
static_cast<double>(CinYAvg/10000000));
            AvgHashTable[AvgHashTable.size()]=AvgCIN;
        }

    }
    for (int i=0; i < AvgHashTable.size(); i++) {
        if (i==0) {
            TopLeft.x=AvgHashTable[i].x;
            TopLeft.y=AvgHashTable[i].y;
            BottomRight.x=AvgHashTable[i].x;
            BottomRight.y=AvgHashTable[i].y;
        }
        else {
           if (AvgHashTable[i].x < TopLeft.x)
               TopLeft.x=AvgHashTable[i].x;
           if (AvgHashTable[i].y < TopLeft.y)
               TopLeft.y=AvgHashTable[i].y;
           if (AvgHashTable[i].x > BottomRight.x)
               BottomRight.x=AvgHashTable[i].x;
           if (AvgHashTable[i].y > BottomRight.y)
               BottomRight.y=AvgHashTable[i].y;
       }
    }
The explanation the first lines are GPS coordinates from a polygon and
i take the average from the 4 points to figure out the centre of the
polygon (I know, geometrically it's not 100% correct but I figured
this should be good enough for me/my polygons) anyways I multiply it
by 10,000,000 in order to get rid of the digits pst the decimal point.
Then after the division by 4 i get two decimal places back....
then i add the numbers to a map in order to be able to easily access
them. type xy is a class with two double variables, x and y. This is
how my globals are declared:
map<int, xy>AvgHashTable;
    xy TopLeft;
    xy BottomRight;
Then i wanna loop through all the elements and figure out the largest
and the smallest value...
somewhere my double values get screwed and i have all weird numbers in
BottomRight as well as in TopLeft

Now my source values are all in the format with 7 decimal numbers. And
in the end I have in TopLeft.x 49.213812599999997 and in BottomRight.x
I got 49.281173000000003... The y values look good for both... any
ideas why these numbers look so awkwardly?

Thanks,
Ron

Try fixed-point arithmetic (http://en.wikipedia.org/wiki/Fixed-
point_arithmetic)
 
C

cerr

Try fixed-point arithmetic (http://en.wikipedia.org/wiki/Fixed-
point_arithmetic)

Thanks for your suggestion, I've now tried it like this:
double CinXAvg =(((sphericalpolygon *) curApproach-
getCheckInPolygon())->getCornerPoints()->at(0).x*10000000 +
((sphericalpolygon *) curApproach-
getCheckInPolygon())->getCornerPoints()->at(1).x*10000000 +
((sphericalpolygon *) curApproach-
getCheckInPolygon())->getCornerPoints()->at(2).x*10000000 +
((sphericalpolygon *) curApproach-
getCheckInPolygon())->getCornerPoints()->at(3).x*10000000)/4;

double CinYAvg =(((sphericalpolygon *) curApproach-
getCheckInPolygon())->getCornerPoints()->at(0).y*10000000 +
((sphericalpolygon *) curApproach-
getCheckInPolygon())->getCornerPoints()->at(1).y*10000000 +
((sphericalpolygon *) curApproach-
getCheckInPolygon())->getCornerPoints()->at(2).y*10000000 +
((sphericalpolygon *) curApproach-
getCheckInPolygon())->getCornerPoints()->at(3).y*10000000)/4;

on the bottom i added following:
cout.setf(ios::fixed,ios::floatfield);
cout.precision(7);
cout << "TopLeft.x: " << TopLeft.x << endl;
cout << "TopLeft.y: " << TopLeft.y << endl;
cout << "BottomRight.x: " << BottomRight.x << endl;
cout << "BottomRight.y: " << BottomRight.y << endl;

and if i print the Bottom right coordinates on a map, they're wrong.
That can't be true, there's a point further down South-East, I'm 100%
sure!
What's going on here? :eek:
Any further suggestions are gladly welcomed!
 
M

mzdude

Thanks for your suggestion, I've now tried it like this:
            double CinXAvg =(((sphericalpolygon *) curApproach->getCheckInPolygon())->getCornerPoints()->at(0).x*10000000 +

                                  ((sphericalpolygon *) curApproach->getCheckInPolygon())->getCornerPoints()->at(1).x*10000000 +

                                  ((sphericalpolygon *) curApproach->getCheckInPolygon())->getCornerPoints()->at(2).x*10000000 +

                                  ((sphericalpolygon *) curApproach-


            double CinYAvg =(((sphericalpolygon *) curApproach->getCheckInPolygon())->getCornerPoints()->at(0).y*10000000 +

                                  ((sphericalpolygon *) curApproach->getCheckInPolygon())->getCornerPoints()->at(1).y*10000000 +

                                  ((sphericalpolygon *) curApproach->getCheckInPolygon())->getCornerPoints()->at(2).y*10000000 +

                                  ((sphericalpolygon *) curApproach-
What's going on here? :eek:
Any further suggestions are gladly welcomed!

It would help us (and you) if you could reduce the example to
double CXinAvg = ( 43.0001247 * 10000000 + // or whatever the number
is
xx.xxxxxxx * ... ) / 4;
....
 
J

Jerry Coffin

(e-mail address removed)>, (e-mail address removed)
says...
Hi There,

I need to do some calculations with GPS coordinates and i get all
weird values and i can't see where i'm going wrong.
My code:
Code:
// calculate the average xy coordinates out of the
polygon's corner points
double CinXAvg =((((sphericalpolygon *) curApproach-[QUOTE]
getCheckInPolygon())->getCornerPoints()->at(0).x +[/QUOTE]
((sphericalpolygon *) curApproach-[QUOTE]
getCheckInPolygon())->getCornerPoints()->at(1).x +[/QUOTE]
((sphericalpolygon *) curApproach-[QUOTE]
getCheckInPolygon())->getCornerPoints()->at(2).x +[/QUOTE]
((sphericalpolygon *) curApproach-[QUOTE]
getCheckInPolygon())->getCornerPoints()->at(3).x)*10000000)/4;[/QUOTE]

double CinYAvg =((((sphericalpolygon *) curApproach-[QUOTE]
getCheckInPolygon())->getCornerPoints()->at(0).y +[/QUOTE]
((sphericalpolygon *) curApproach-[QUOTE]
getCheckInPolygon())->getCornerPoints()->at(1).y +[/QUOTE]
((sphericalpolygon *) curApproach-[QUOTE]
getCheckInPolygon())->getCornerPoints()->at(2).y +[/QUOTE]
((sphericalpolygon *) curApproach-[QUOTE]
getCheckInPolygon())->getCornerPoints()->at(3).y)*10000000)/4;[/QUOTE]
//save the average value in a hash table so we can later
go ahead and find the outest polygons
xy AvgCIN(static_cast<double>(CinXAvg/10000000),
static_cast<double>(CinYAvg/10000000));[/QUOTE]

I hope you don't mind my being blunt, but this is hard to read, and 
so ugly I'd rather not. I'd write it something like this:

std::vector<xy> const &xys = 
    *((sphericalpolygon *) curApproach->getCheckInPolygon())->
        getCornerPoints();

Without seeing the rest of the code, it's hard to say for sure, but 
nothing you said or shown indicates that the cast should be necessary 
-- I'd look hard at trying to eliminate it.

With that in place, the averaging code reduces to something like 
this:

double CinXAvg = (xys[0].x + xys[1].x + xys[2].x + xys[3].x)*0.25;
double CinYAvg = (xys[0].y + xys[1].y + xys[2].y + xys[3].y)*0.25;

The multiplication, and later division by 10,000,000 were not 
accomplishing much of anything, and certainly not what you seemed to 
think, so at least for now I've simply eliminated them. If you want 
to round the numbers to some specified precision, I'd write a small 
function for exactly that purpose:
	round(CinXAvg, 7);
	round(CinYAvg, 7);
[QUOTE]
AvgHashTable[AvgHashTable.size()]=AvgCIN;[/QUOTE]

You only ever seem to add to the end of the "hash table" (which you 
later show is a map, NOT a hash table at all). Given that you only 
add to its end, and the keys are contiguous integers starting from 
zero, an std::vector appears to be what you really want:

	std::vector<xy> means;

	means.push_back(xy(CinXAvg, CinYAvg));
[QUOTE]
}
for (int i=0; i < AvgHashTable.size(); i++) {
if (i==0) {
TopLeft.x=AvgHashTable[i].x;
TopLeft.y=AvgHashTable[i].y;
BottomRight.x=AvgHashTable[i].x;
BottomRight.y=AvgHashTable[i].y;
}
else {
if (AvgHashTable[i].x < TopLeft.x)
TopLeft.x=AvgHashTable[i].x;
if (AvgHashTable[i].y < TopLeft.y)
TopLeft.y=AvgHashTable[i].y;
if (AvgHashTable[i].x > BottomRight.x)
BottomRight.x=AvgHashTable[i].x;
if (AvgHashTable[i].y > BottomRight.y)
BottomRight.y=AvgHashTable[i].y;
}
}[/QUOTE]

Here, I'd move the special case out of the loop, and use std::min and 
std::max:

	xy TopLeft = means[0];
	xy BottomRight = means[0];

	for (int i=1; i<means.size(); ++i) {
		TopLeft.x = std::min(TopLeft.x, means[i].x);
		TopLeft.y = std::min(TopLeft.y, means[i].y);
		BottomRight.x = std::max(BottomRight.x, means[i].x);
		BottomRight.y = std::max(BottomRight.y, means[i].y);
	}

This may be part of the source of your problem. At least in the usual 
scheme of things, larger Y coordinates correspond to "up" and smaller 
Y coordinates to "down". Assuming that's the case here, your TopLeft 
is really the at the bottom left, and your BottomRight is really the 
top right.

[ ... ]
[QUOTE]
I multiply it
by 10,000,000 in order to get rid of the digits pst the decimal point.[/QUOTE]

How do you figure that multiplying a floating point number is going 
to truncate numbers after the decimal point? As I said above, I'd 
skip the rounding for now, but when/if you decide you really need it, 
write a function specifically for that purpose, and test it 
thoroughly to get a reasonable idea that it at least stands some 
chance of doing what you want.
[QUOTE]
Then after the division by 4 i get two decimal places back....[/QUOTE]

What makes you think it's going to be rounded to two decimal places? 
I see nothing that would seem to do any such rounding or truncating.
[QUOTE]
then i add the numbers to a map in order to be able to easily access
them. type xy is a class with two double variables, x and y. This is
how my globals are declared:
map<int, xy>AvgHashTable;[/QUOTE]

"HashTable" strikes me as a lousy name. First of all, std::map isn't 
implemented as a hash table, so it's misleading, and second, even if 
it was a hash table, that would be an irrelevant implementation 
detail anyway.

Worse than that, as noted above, you seem to be using it purely as a 
slow, bulky replacement for a vector anyway. You'd be better off 
using a vector and being done with it.
[QUOTE]
Now my source values are all in the format with 7 decimal numbers.
And in the end I have in TopLeft.x 49.213812599999997 and in
BottomRight.x I got 49.281173000000003... The y values look good
for both... any ideas why these numbers look so awkwardly?[/QUOTE]

It's hard to say more with certainty. Your problem could stem from 
either the defective attempt at rounding, or the confusion between 
top and bottom, or there could be something else involved entirely 
(as noted above, the cast is suspicious at best).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top