Hello, I have been tasked with writing a test application to convert between geographic coordinate systems. Now math is not my strong suit but I was assured I wouldn't actually have to do any of the calculations since the formulas are provided. The trouble is trying to get the lengthy formulas written in C++ so that the order of operations stays the same.

Like I said, math is not my strong suit, generally I see a lengthy equation and I go all cross eyed. And since I'm not getting to correct answers from my program I'm going to assume its a math error somewhere.

Anyway, I was hoping someone with a little more mathematical know how might take a crack at formatting these equations for C++.

Here's how I have them written:

float K1 = M * k0;
	float K2 = k0 * nu * ((sin(2 * lat))/4);
	float K3 = ((k0 * nu * sin(lat)) * (pow(cos(lat),3))/24) * ((5 - pow(tan(lat),2)) + (9* esq * pow(cos(lat),2)) + (4 * pow(esq,2) * pow(cos(lat),4)));

	float y = K1 + (K2 * pow(p,2)) + (K3 * pow(p,4));
	float northing = y;

	float K4 = k0 * nu * cos(lat);
	float K5 = ((k0 * nu * pow(cos(lat),3))/6) * (1 - (pow(tan(lat),2) + (esq * pow(cos(lat),2))));

	float x =  (K4 * p) + (K5 * pow(p,3));
	float easting = x;

and I've attached a screen shot of the formulas presented to me rather try and mess with formatting superscripts :D

Attachments equations.png 11.19 KB

You have one too many parenthesis on line 10, it should be:

float K5 = ((k0 * nu * pow(cos(lat),3))/6) * (1 - pow(tan(lat),2) + (esq * pow(cos(lat),2)));

Notice that there is no parenthesis just before pow(tan(lat),2) , this was causing the subtraction to distribute over the next term, thus, flipping its sign.

The priority of operations in C++ is the same as for regular math, so you don't need to abuse parentheses that much. You should also store intermediate values that require expensive computations, like cos and sin. And try to reuse previously calculated values as well. Finally, you should avoid using the pow() function for integer powers, it is more economical to expand the multiplication. With that in mind, you could have:

float cl = cos(lat); float clsq = cl * cl;
  float sl = sin(lat); float slsq = sl * sl; //pre-compute cos and sin.
  
  float K1 = M * k0;
  float K2 = 0.5 * k0 * nu * sl * cl;
  float K3 = (K2 / 12.0) * (clsq * (5.0 + esq * clsq * (9.0 + 4.0 * esq * clsq)) - slsq);
  
  float y = K1 + p * p * (K2 + K3 * p * p);
  float northing = y;

  float K4 = k0 * nu * cl;
  float K5 = (K4 / 6.0) * (clsq * (1.0 + esq * clsq) - slsq);

  float x =  p * (K4 + K5 * p * p);
  float easting = x;

I also eliminated the tan() in the equation, because tan() can be singular and it is generally a good idea to avoid it, and you always can through trigonometric identities.

My abuse of parenthesis is generally my way of organizing things in math. Like I said, it's really my weak spot. But thank you. This looks a lot cleaner. I'll make the adjustments and cross my fingers.

ETA: Well, I suppose it wasn't a math error, at least not in that section. Plugging in your fixed equations gives me the same results, so something else somewhere is going awry. Thanks again. Back to troubleshooting.

Edited 5 Years Ago by dyingatmidnight: n/a

I don't see where u got rid of the tan :S Tan = cos#/sin#.. I don't see that anywhere :S

And this is what I used:

float K1 = (M * K0);
	float K2 = (K0 * nu) * ((sin(2 * lat))/4);
	float K3 = (((k0 * nu) * sin(lat)) * ((pow(cos(lat), 3))/24) * (5 - (pow(tan(lat), 2)))) + ((9 * esq) * (pow(cos(lat), 2))) + ((4 * (pow(esq, 2))) * (pow(cos(lat), 4)));
	
	float y = K1 + (K2 * (pow(p, 2))) + (K3 * (pow(p, 4)));
	float northing = y;
	
	float K4 = (K0 * nu * cos(lat));
	float K5 = ((k0 * nu * (pow(cos(lat), 3)))/6) * (1 - ((pow(tan(lat), 2)) + (esq * (pow(cost(lat), 2)))));
	
	float x = (K4 * p) + (K5 * (pow(p, 3)));
	float easting = x;

I did the bedmas myself so I put the brackets in the right spot assuming his equations were right in the first place, the bedmas in the above would be correct.

>>don't see where u got rid of the tan Tan = cos#/sin#.. I don't see that anywhere

First of all, tan = sin / cos, not the other way around. I got rid of the tan^2 terms by noticing that everywhere the tan^2 appears, it is multiplied by a cos^2, which I distributed on the addition, and, of course, giving tan^2 cos^2 = sin^2. So the tan^2 turned into sin^2. Then I collected the terms again to reduce the number of flops to a minimum. This is high-school math, not rocket-science (and I've done rocket science). Getting rid of tan is important because tan can go to +- infinity (divide by zero), so if the tan is avoidable, then it should be, for sake of numerical stability.

Thank you both, I seem to have it working now within a certain margin of error. Can't be certain if the sample numbers I'm using are correct or even what the sig figs are like in their calculations. But it works to my satisfaction at the moment.

This question has already been answered. Start a new discussion instead.