So I'm running iterations with this formula:
double x = 10 / 0.25 * ((0.0002 * x1 * (10 - 0.25 * x1)) + 0.00217 * x2 * (20 - 0.25 * x2)); With this process: Xn+1 = f(Xn).
And if you start from negative X you will eventually end up with (-/+) infinity, so after 6 iterations I'm supposed to get infinity, but what I got surprised me and I couldn't find anywhere what that is, I got "-?", I've tried comparing it to +/- infinity and tried to compare it to int numbers just to clarify what it is, but I cant get anything out of it, for example, I've tried if ("-?" > 1000) break;, and it doesn't outcome as "true". Neither am I getting any errors by comparing it to int/double, I need to stop iterations when I start going into infinity, how can I do that?
code:
public static double CalculateX1(double x1, double x2)
{
double x = 10 / 0.25 * ((0.0002 * x1 * (10 - 0.25 * x1)) + 0.00217 * x2 * (20 - 0.25 * x2));
return x;
}
public static double CalculateX2(double x2, double x1)
{
double y = 20 / 0.25 * ((0.00052 * x2 * (20 - 0.25 * x2)) + 0.0075 * x1 * (10 - 0.25 * x1));
return y;
}
static void Main(string[] args)
{
string writePath = #"C:\Users\evluc\Desktop\cord.txt";
double X = -5;
double Y = -5;
int pointer = 1;
double[,] coordinates = new double[10001, 2];
coordinates[0, 0] = X;
coordinates[0, 1] = Y;
for (int i = 0; i < 5000; i++)
{
//double XTemp = CalculateX1(X, Y);
//double YTemp = CalculateX2(Y, X);
//X = CalculateX1(coordinates[pointer - 1, 0], coordinates[pointer - 1, 1]);
//Y = CalculateX2(coordinates[pointer - 1, 1], coordinates[pointer - 1, 0]);
coordinates[pointer, 0] = CalculateX1(coordinates[pointer - 1, 0], coordinates[pointer - 1, 1]);
coordinates[pointer, 1] = CalculateX2(coordinates[pointer - 1, 1], coordinates[pointer - 1, 0]);
pointer++;
if (Math.Abs(coordinates[pointer, 0]) > 1000 || Math.Abs(coordinates[pointer, 1]) > 1000)
{
Console.WriteLine("infinity");
Console.ReadKey();
}
}
for (int i = 0; i < 5000; i++)
{
Console.WriteLine("X = " + coordinates[i, 0] + "," + "Y = " + coordinates[i, 1] + "; ");
}
}
I think whatever you use to display/inspect the value cannot print ∞.
double d = double.MinValue;
d *= 2;
Console.WriteLine($"{d}: IsInfinity: {double.IsNegativeInfinity(d)}");
-∞: IsInfinity: True
Stopping at infinity
Here's a loop that stops at infinity:
double d = 2;
var i = 1;
while(!double.IsInfinity(d))
{
d = i*d*d;
i = -i;
}
Console.WriteLine(d);
-∞
int a=6378137;
int A0=6367449;
double B0=16038.43;
double C0=16.83261;
double D0=0.021984;
double E0= 0.000313;
double k0=0.9996;
double e1=0.081819;
double e1sq = 0.006739497;
double m = -120;
double l = 60;
int n = 11;
int o = 6 *n- 183;
double p = ((m - o) * 0.01744444);
double q = l * 0.0174444;
double r = m * 0.0174444;
double s = a * (1 - e1 * e1) / (1 - ((e1 * Math.Sin(q)) * (e1 * Math.Sin(q))*(e1 * Math.Sin(q))));
double t = a / ((1 - (e1 * Math.Sin(q))));
double v = A0 * q - B0 * Math.Sin(2 * q) + C0 * Math.Sin(4 * q) - D0 * Math.Sin(6 * q) + E0 * Math.Sin(8 * q);
double x = v * k0;
double y = t * Math.Sin(q) * Math.Cos(q) / 2;
double z = (t * Math.Sin(q) * (Math.Cos(q)* Math.Cos(q)*Math.Cos(q)) / 24) * (5 - (Math.Tan(q)* Math.Tan(q)) + 9 * e1sq * (Math.Cos(q) *Math.Cos(q)) + 4 * e1sq *e1sq * (Math.Cos(q)*Math.Cos(q)*Math.Cos(q)*Math.Cos(q)) ) * k0;
double AA = t * Math.Cos(q) * k0;
double AB = (Math.Cos(q)*Math.Cos(q)*Math.Cos(q)) * (t / 6) * (1 - (Math.Tan(q) *Math.Tan(q)) + e1sq * (Math.Cos(q) *Math.Cos(q))) * k0;
double AC = ((p * p * p * p * p * p) * t * Math.Sin(q) * (Math.Cos(q) * Math.Cos(q) * Math.Cos(q) * Math.Cos(q) * Math.Cos(q)) / 720) * (61 - 58 * (Math.Tan(q) * Math.Tan(q)) + (Math.Tan(q) * Math.Tan(q) * Math.Tan(q) * Math.Tan(q)) + 270 * e1sq * (Math.Cos(q) * Math.Cos(q)) - 330 * e1sq * (Math.Sin(q) * Math.Sin(q))) * k0;
double AD = (x+y*p*p+z*(p*p*p*p));
double AE;
double AF;
if (AD < 0)
{
AE = (10000000 + AD);
}
else {
AE = AD;
}
AF = 500000 + (AA * p + AB * (p * p * p));
using (StreamWriter writer = new StreamWriter(#"C:\Users\dcf\Desktop\out.txt"))
{
writer.WriteLine("north:{0}",AE);
writer.WriteLine("east:{0}",AF);
}
This is my code where m and l value should have the value from text file. my text file looks like
m,l
56536716.534,43843327.880
56584832.507,43501825.240
56669161.226,43199470.844
56715913.464,42856275.950
56782842.247,42435886.070
56810019.308,42071222.859
56836462.600,41706208.191
56900872.591,41282609.754
i need to read m and l value directly from my text file to do calcultion.
Assuming the values for m and l are alternating in your textfile.
First you should read in the file, split the values by a delimter(e.g. ",") and assign them to variables m and l. Then you can call your calculation-function for each
private void readFile(pathToFile)
{
var textfilecontent= File.ReadAllLines(pathToFile);
for (int i = 1; i < textfilecontent.Length; i++)
{
// splits the values at delimiter ,
var valPerLine = textfilecontent[i].Split(',');
// only works if you have only two numbers per line
calculate(Convert.ToDouble(valPerLine[0]), Convert.ToDouble(valPerLine[1]))
}
}
private void calculate(double m, double l)
{
// your formulas, m and l should now be inserted as parameter
int a=6378137;
int A0=6367449;
double B0=16038.43;
double C0=16.83261;
double D0=0.021984;
double E0= 0.000313;
double k0=0.9996;
double e1=0.081819;
double e1sq = 0.006739497;
//double m = -120;
//double l = 60;
int n = 11;
int o = 6 *n- 183;
double p = ((m - o) * 0.01744444);
double q = l * 0.0174444;
double r = m * 0.0174444;
double s = a * (1 - e1 * e1) / (1 - ((e1 * Math.Sin(q)) * (e1 * Math.Sin(q))*(e1 * Math.Sin(q))));
double t = a / ((1 - (e1 * Math.Sin(q))));
double v = A0 * q - B0 * Math.Sin(2 * q) + C0 * Math.Sin(4 * q) - D0 * Math.Sin(6 * q) + E0 * Math.Sin(8 * q);
double x = v * k0;
double y = t * Math.Sin(q) * Math.Cos(q) / 2;
double z = (t * Math.Sin(q) * (Math.Cos(q)* Math.Cos(q)*Math.Cos(q)) / 24) * (5 - (Math.Tan(q)* Math.Tan(q)) + 9 * e1sq * (Math.Cos(q) *Math.Cos(q)) + 4 * e1sq *e1sq * (Math.Cos(q)*Math.Cos(q)*Math.Cos(q)*Math.Cos(q)) ) * k0;
double AA = t * Math.Cos(q) * k0;
double AB = (Math.Cos(q)*Math.Cos(q)*Math.Cos(q)) * (t / 6) * (1 - (Math.Tan(q) *Math.Tan(q)) + e1sq * (Math.Cos(q) *Math.Cos(q))) * k0;
double AC = ((p * p * p * p * p * p) * t * Math.Sin(q) * (Math.Cos(q) * Math.Cos(q) * Math.Cos(q) * Math.Cos(q) * Math.Cos(q)) / 720) * (61 - 58 * (Math.Tan(q) * Math.Tan(q)) + (Math.Tan(q) * Math.Tan(q) * Math.Tan(q) * Math.Tan(q)) + 270 * e1sq * (Math.Cos(q) * Math.Cos(q)) - 330 * e1sq * (Math.Sin(q) * Math.Sin(q))) * k0;
double AD = (x+y*p*p+z*(p*p*p*p));
double AE;
double AF;
if (AD < 0)
{
AE = (10000000 + AD);
}
else
{
AE = AD;
}
AF = 500000 + (AA * p + AB * (p * p * p));
using (StreamWriter writer = new StreamWriter(#"C:\Users\dcf\Desktop\out.txt"))
{
writer.WriteLine("north:{0}",AE);
writer.WriteLine("east:{0}",AF);
}
}
I am struggling to replicate the following fortran 77 subroutine into C# method. The main problem is that I am trying to get rid of the fortran's goto statements.
The fortran to C# conversion looks fine, still the goto statements remained. Is there a way all of them can be replaced with conditionals or some other ways? Thank you.
Here is the fortran subroutine:
C PROGRAM TEMP
subroutine TEMP (acl,adu,aeff,c,cair,cb,cbare,
+ cclo,count1,csum,di,ed,emcl,emsk,enbal,
+ enbal2,ere,erel,esw,eswdif,eswphy,eswpot,
+ evap,facl,fcl,fec,feff,food,h,hc,he,ht,htcl,icl,j,
+ mbody,p,po,r1,r2,rbare,rcl,
+ rclo,rclo2,rdcl,rdsk,rob,rsum,sex,sigm,sw,swf,swm,
+ ta,tbody,tcl,tcore,tmrt,tsk,v,vb,vb1,vb2,
+ vpa,vpts,wetsk,wd,wr,ws,wsum,xx)
real acl,adu,aeff,c(0:10),cair,cb,cbare,
+ cclo,csum,di,ed,emcl,emsk,enbal,
+ enbal2,ere,erel,esw,eswdif,eswphy,eswpot,
+ evap,facl,fcl,fec,feff,food,h,hc,he,ht,htcl,icl,
+ mbody,p,po,r1,r2,rbare,rcl,
+ rclo,rclo2,rdcl,rdsk,rob,rsum,sigm,sw,swf,swm,
+ ta,tbody,tcl,tcore(1:7),tmrt,tsk,v,vb,vb1,vb2,
+ vpa,vpts,wetsk,wd,wr,ws,wsum,xx
integer count1,count3,j,sex
wetsk = 0.
adu = 0.203 * mbody ** 0.425 * ht ** 0.725
hc = 2.67 + ( 6.5 * v ** 0.67)
hc = hc * (p /po) ** 0.55
feff = 0.725
C
facl = (- 2.36 + 173.51 * icl - 100.76 * icl * icl + 19.28
+ * (icl ** 3.)) / 100.
C
if (facl .gt.1.) facl = 1.
rcl = (icl/6.45)/facl
if (icl.ge.2.) y = 1.
if ((icl .gt. 0.6) .and. (icl .lt. 2.)) y = (ht - 0.2) / ht
if ((icl .le. 0.6) .and. (icl .gt. 0.3)) y = 0.5
if ((icl .le. 0.3) .and. (icl .gt. 0.)) y = 0.1
r2 = adu * (fcl - 1. + facl) / (2. * 3.14 * ht * y)
r1 = facl * adu / (2. * 3.14 * ht * y)
di = r2 - r1
C TEMPERATURE
do 90 j = 1,7
tsk = 34.
count1 = 0
tcl = (ta + tmrt + tsk) / 3.
count3 = 1
enbal2 = 0.
20 acl = adu * facl + adu * (fcl - 1.)
rclo2 = emcl*sigm *((tcl+273.2)** 4.-(tmrt+273.2)** 4.)*feff
htcl = 6.28 * ht * y * di / (rcl * alog(r2/r1) * acl)
tsk = 1. / htcl * (hc * (tcl - ta) + rclo2) + tcl
C RADIATION
aeff = adu * feff
rbare = aeff * (1.-facl) * emsk * sigm *
+ ((tmrt + 273.2) ** 4. - (tsk + 273.2) ** 4.)
rclo = feff * acl * emcl * sigm *
+ ((tmrt + 273.2) ** 4. - (tcl + 273.2) ** 4.)
rsum = rbare + rclo
C CONVECT
cbare = hc * (ta - tsk) * adu * (1. - facl)
cclo = hc * (ta - tcl ) * acl
csum = cbare + cclo
C CORE
c(0) = h + ere
c(1) = adu * rob * cb
c(2) = 18. - 0.5 * tsk
c(3) = 5.28 * adu * c(2)
c(4) = 0.0208 * c(1)
c(5) = 0.76075 * c(1)
c(6) = c(3) - c(5) - tsk * c(4)
c(7) = - c(0) * c(2) - tsk * c(3) + tsk * c(5)
c(8) = c(6) * c(6) - 4. * c(4) * c(7)
c(9) = 5.28 * adu - c(5) - c(4) * tsk
c(10) = c(9) * c(9) - 4. * c(4) *
+ (c(5) * tsk - c(0) - 5.28 * adu * tsk)
C
if (tsk.eq.36.) tsk=36.01
tcore(7) = c(0) / (5.28 * adu + c(1) * 6.3 / 3600.) + tsk
tcore(3) = c(0) / (5.28 * adu + (c(1) * 6.3 / 3600.) /
+ (1 + 0.5 * (34. -tsk))) + tsk
if (c(10) .lt. 0.) goto 22
tcore(6) = (- c(9) - c(10) ** 0.5) / (2. * c(4))
tcore(1) = (- c(9) + c(10) ** 0.5) / (2. * c(4))
22 if (c(8) .lt. 0.) goto 24
tcore(2) = (- c(6) + abs(c(8)) ** 0.5) / (2. * c(4))
tcore(5) = (- c(6) - abs(c(8)) ** 0.5) / (2. * c(4))
24 tcore(4) = c(0) / (5.28 * adu + c(1) * 1. / 40.) + tsk
C TRANSPARENCE
tbody = 0.1 * tsk + 0.9 * tcore (j)
swm = 304.94 * (tbody - 36.6) * adu / 3600000.
vpts = 6.11 * 10. ** (7.45 * tsk / (235. + tsk))
if (tbody .le. 36.6) swm = 0.
swf = 0.7 * swm
if(sex .eq. 1) sw = swm
if(sex .eq. 2) sw = swf
eswphy = - sw * evap
he = 0.633 * hc / (p * cair)
fec = 1. / (1. + 0.92 * hc * rcl)
eswpot = he * (vpa - vpts) * adu * evap * fec
wetsk = eswphy / eswpot
if (wetsk .gt. 1.) wetsk = 1.
eswdif = eswphy - eswpot
if (eswdif .le. 0.) esw = eswpot
if (eswdif .gt. 0.) esw = eswphy
if (esw .gt. 0.) esw = 0.
C DIFFERENCE
rdsk = 0.79 * 10. ** 7.
rdcl = 0.
ed = evap / (rdsk + rdcl) * adu * (1 - wetsk) * (vpa-vpts)
C VB
vb1 = 34. - tsk
vb2 = tcore(j) - 36.6
if (vb2 .lt.0.) vb2 = 0.
if (vb1 .lt.0.) vb1 = 0.
vb = (6.3 + 75. * (vb2)) / (1. + 0.5 * vb1)
C BALANCE
enbal = h + ed + ere + esw + csum + rsum + food
C COVER
if (count1 .eq.0) xx = 1.
if (count1 .eq.1) xx = 0.1
if (count1 .eq.2) xx = 0.01
if (count1 .eq.3) xx = 0.001
if (enbal .gt. 0.) tcl = tcl + xx
if (enbal .lt. 0.) tcl = tcl - xx
if ((enbal .le. 0.) .and. (enbal2 .gt. 0.)) goto 30
if ((enbal .ge. 0.) .and. (enbal2 .lt. 0.)) goto 30
enbal2 = enbal
count3 = count3 + 1
C
if (count3 .gt. 200) goto 30
goto 20
30 if ((count1 .eq.0.).or.(count1.eq.1.).or.(count1.eq.2.)) then
count1 = count1 + 1.
enbal2 = 0.
goto 20
end if
C
if (count1 .eq. 3.) then
C
if ((j .eq. 2) .or. (j .eq. 5)) goto 40
if ((j .eq. 6) .or. (j .eq. 1)) goto 50
if (j .eq. 3) goto 60
if (j .eq. 7) goto 70
if (j .eq. 4) goto 80
end if
40 if (c(8) .lt. 0.) goto 90
if ((tcore(j) .ge. 36.6) .and. (tsk .le. 34.050)) goto 80
goto 90
50 if (c(10) .lt. 0. ) goto 90
if ((tcore(j) .ge. 36.6) .and. (tsk .gt. 33.850)) goto 80
goto 90
60 if ((tcore(j) .lt. 36.6) .and. (tsk .le. 34.000)) goto 80
goto 90
70 if ((tcore(j) .lt. 36.6) .and. (tsk .gt. 34.000)) goto 80
goto 90
80 if ((j .ne. 4) .and. (vb .ge. 91.)) goto 90
if ((j. eq. 4) .and. (vb .lt. 89.)) goto 90
if (vb .gt. 90.) vb = 90.
C LOSSES
ws = sw * 3600. * 1000.
if (ws .gt.2000.) ws = 2000.
wd = ed / evap * 3600. * (-1000.)
wr = erel / evap * 3600. * (-1000.)
wsum = ws + wr + wd
goto 100
90 continue
100 return
end
And here is the C# attempt to replicate the upper fortran subroutine:
using System;
public static class GlobalMembers_TEMP
{
//C PROGRAM TEMP
// --------------------------------------------
public static void TEMP(acl, adu, aeff, c, cair, cb, cbare, cclo, count1, csum, di, ed , emcl , emsk , enbal , enbal2 , ere , erel , esw , eswdif , eswphy , eswpot , evap , facl , fcl , fec , feff , food , h , hc , he , ht , htcl , icl , j , mbody , p , po , r1 , r2 , rbare , rcl , rclo , rclo2 , rdcl , rdsk , rob , rsum , sex , sigm , sw , swf , swm , ta , tbody , tcl, tcore , tmrt , tsk , v , vb , vb1 , vb2 , vpa , vpts , wetsk , wd , wr , ws , wsum , xx)
{
float acl;
float adu;
float aeff;
float[] c = new float[11]; // ???
float cair;
float cb;
float cbare;
float cclo;
float csum;
float di;
float ed;
float emcl;
float emsk;
float enbal;
float enbal2;
float ere;
float erel;
float esw;
float eswdif;
float eswphy;
float eswpot;
float evap;
float facl;
float fcl;
float fec;
float feff;
float food;
float h;
float hc;
float he;
float ht;
float htcl;
float icl;
float mbody;
float p;
float po;
float r1;
float r2;
float rbare;
float rcl;
float rclo;
float rclo2;
float rdcl;
float rdsk;
float rob;
float rsum;
float sigm;
float sw;
float swf;
float swm;
float ta;
float tbody;
float tcl;
float[] tcore = new float[7]; // ???
float tmrt;
float tsk;
float v;
float vb;
float vb1;
float vb2;
float vpa;
float vpts;
float wetsk;
float wd;
float wr;
float ws;
float wsum;
float xx;
int count1;
int count3;
int j;
int sex;
wetsk = 0.0;
adu = 0.203 * mbody * *0.425 * ht * *0.725;
hc = 2.67 + (6.5 * v * *0.67);
hc = hc * (p / po) * *0.55;
feff = 0.725;
//C rcl = icl / 6.45
facl = (-2.36 + 173.51 * icl - 100.76 * icl * icl + 19.28 * (icl * *3.0)) / 100.0;
//C
if (facl > 1.0)
{
facl = 1.0;
}
rcl = (icl / 6.45) / facl;
if (icl >= 2.0)
{
y = 1.0;
}
if ((icl > 0.6)) && ((icl < 2.0))
{
y = (ht - 0.2) / ht;
}
if ((icl <= 0.6)) && ((icl > 0.3))
{
y = 0.5;
}
if ((icl <= 0.3)) && ((icl > 0.0))
{
y = 0.1;
}
r2 = adu * (fcl - 1.0 + facl) / (2.0 * 3.14 * ht * y);
r1 = facl * adu / (2.0 * 3.14 * ht * y);
di = r2 - r1;
//C TEMPERATURE
for (90 j = 1, 7)
{
tsk = 34.0;
count1 = 0;
tcl = (ta + tmrt + tsk) / 3.0;
count3 = 1;
enbal2 = 0.0;
g20:
acl = adu * facl + adu * (fcl - 1.0);
rclo2 = emcl * sigm * ((tcl + 273.2) * *4.0 - (tmrt + 273.2) * *4.0) * feff;
htcl = 6.28 * ht * y * di / (rcl * alog(r2 / r1) * acl);
tsk = 1.0 / htcl * (hc * (tcl - ta) + rclo2) + tcl;
//C RADIATION
aeff = adu * feff;
rbare = aeff * (1.0 - facl) * emsk * sigm * ((tmrt + 273.2) * *4.0 - (tsk + 273.2) * *4.0);
rclo = feff * acl * emcl * sigm * ((tmrt + 273.2) * *4.0 - (tcl + 273.2) * *4.0);
rsum = rbare + rclo;
//C CONVECT
cbare = hc * (ta - tsk) * adu * (1.0 - facl);
cclo = hc * (ta - tcl) * acl;
csum = cbare + cclo;
//C CORE
c[0] = h + ere;
c[1] = adu * rob * cb;
c[2] = 18.0 - 0.5 * tsk;
c[3] = 5.28 * adu * c[2];
c[4] = 0.0208 * c[1];
c[5] = 0.76075 * c[1];
c[6] = c[3] - c[5] - tsk * c[4];
c[7] = -c[0] * c[2] - tsk * c[3] + tsk * c[5];
c[8] = c[6] * c[6] - 4.0 * c[4] * c[7];
c[9] = 5.28 * adu - c[5] - c[4] * tsk;
c[10] = c[9] * c[9] - 4.0 * c[4] * (c[5] * tsk - c[0] - 5.28 * adu * tsk);
//C
if (tsk == 36.0)
{
tsk = 36.01;
}
tcore[7] = c[0] / (5.28 * adu + c[1] * 6.3 / 3600.0) + tsk;
tcore[3] = c[0] / (5.28 * adu + (c[1] * 6.3 / 3600.0) / (1 + 0.5 * (34.0 - tsk))) + tsk;
if (c[10] < 0.0)
{
goto g22;
}
tcore[6] = (-c[9] - c[10] * *0.5) / (2.0 * c[4]);
tcore[1] = (-c[9] + c[10] * *0.5) / (2.0 * c[4]);
g22:
if (c[8] < 0.0)
{
goto g24;
}
tcore[2] = (-c[6] + Math.Abs(c[8]) * *0.5) / (2.0 * c[4]);
tcore[5] = (-c[6] - Math.Abs(c[8]) * *0.5) / (2.0 * c[4]);
g24:
tcore[4] = c[0] / (5.28 * adu + c[1] * 1.0 / 40.0) + tsk;
//C TRANSPARENCE
tbody = 0.1 * tsk + 0.9 * tcore[j];
swm = 304.94 * (tbody - 36.6) * adu / 3600000.0;
vpts = 6.11 * 10.0 * *(7.45 * tsk / (235.0 + tsk));
if (tbody <= 36.6)
{
swm = 0.0;
}
swf = 0.7 * swm;
if (sex == 1)
{
sw = swm;
}
if (sex == 2)
{
sw = swf;
}
eswphy = -sw * evap;
he = 0.633 * hc / (p * cair);
fec = 1.0 / (1.0 + 0.92 * hc * rcl);
eswpot = he * (vpa - vpts) * adu * evap * fec;
wetsk = eswphy / eswpot;
if (wetsk > 1.0)
{
wetsk = 1.0;
}
eswdif = eswphy - eswpot;
if (eswdif <= 0.0)
{
esw = eswpot;
}
if (eswdif > 0.0)
{
esw = eswphy;
}
if (esw > 0.0)
{
esw = 0.0;
}
//C DIFFERENCE
rdsk = 0.79 * 10.0 * *7.0;
rdcl = 0.0;
ed = evap / (rdsk + rdcl) * adu * (1 - wetsk) * (vpa - vpts);
//C VB
vb1 = 34.0 - tsk;
vb2 = tcore[j] - 36.6;
if (vb2 < 0.0)
{
vb2 = 0.0;
}
if (vb1 < 0.0)
{
vb1 = 0.0;
}
vb = (6.3 + 75.0 * (vb2)) / (1.0 + 0.5 * vb1);
//C BALANCE
enbal = h + ed + ere + esw + csum + rsum + food;
//C COVER
if (count1 == 0)
{
xx = 1.0;
}
if (count1 == 1)
{
xx = 0.1;
}
if (count1 == 2)
{
xx = 0.01;
}
if (count1 == 3)
{
xx = 0.001;
}
if (enbal > 0.0)
{
tcl = tcl + xx;
}
if (enbal < 0.0)
{
tcl = tcl - xx;
}
if ((enbal <= 0.0)) && ((enbal2 > 0.0))
{
goto g30;
}
if ((enbal >= 0.0)) && ((enbal2 < 0.0))
{
goto g30;
}
enbal2 = enbal;
count3 = count3 + 1;
//C
if (count3 > 200)
{
goto g30;
}
goto g20;
g30:
if ((count1 == 0.0))
{
|| ((count1 == 1.0)) || ((count1 == 2.0))
{
count1 = count1 + 1.0;
enbal2 = 0.0;
goto g20;
}
}
//C
if (count1 == 3.0)
{
//C
if ((j == 2))
{
|| ((j == 5)) goto g40;
}
if ((j == 6))
{
|| ((j == 1)) goto g50;
}
if (j == 3)
{
goto g60;
}
if (j == 7)
{
goto g70;
}
if (j == 4)
{
goto g80;
}
}
g40:
if (c[8] < 0.0)
{
goto g90;
}
if ((tcore[j] >= 36.6)) && ((tsk <= 34.050))
{
goto g80;
}
goto g90;
g50:
if (c[10] < 0.0)
{
goto g90;
}
if ((tcore[j] >= 36.6)) && ((tsk > 33.850))
{
goto g80;
}
goto g90;
g60:
if ((tcore[j] < 36.6)) && ((tsk <= 34.000))
{
goto g80;
}
goto g90;
g70:
if ((tcore[j] < 36.6)) && ((tsk > 34.000))
{
goto g80;
}
goto g90;
g80:
if ((j != 4)) && ((vb >= 91.0))
{
goto g90;
}
if ((j.eq.4)) && ((vb < 89.0))
{
goto g90;
}
if (vb > 90.0)
{
vb = 90.0;
}
//C LOSSES
ws = sw * 3600.0 * 1000.0;
if (ws > 2000.0)
{
ws = 2000.0;
}
wd = ed / evap * 3600.0 * (-1000.0);
wr = erel / evap * 3600.0 * (-1000.0);
wsum = ws + wr + wd;
goto g100;
}
g100:
return;
}
}
You can try to turn this code into a state machine where each state represents a single goto inside the loop.
For that you will need to turn your method into a class, that contains all the parameters and variables as class fields, and has one constructor that initializes appropriate fields and (optionally) runs the "method".
I won't transition your method because it is far too huge as an example, but I will give you the following:
Original not converted method:
public static void Do(Int32 param1, Int32 param2)
{
Int32 loopI;
Int32 outBefore,
outAfter,
outGoto1 = 0,
outGoto2 = 0;
Int32[] outValues = new Int32[7];
Console.WriteLine("METHOD:");
Console.WriteLine("DoBeforeLoop");
outBefore = param1 + param2;
Boolean wasInGoto2 = false;
for (loopI = 0; loopI < 7; loopI++)
{
Console.WriteLine("Iteration {0}", loopI);
Console.WriteLine("FortranLoopMethodState.LoopCycleStart");
outValues[loopI] = loopI;
goto1:
Console.WriteLine("FortranLoopMethodState.Goto1");
outGoto1 = loopI + param1;
if (wasInGoto2)
{
wasInGoto2 = false;
goto end;
}
wasInGoto2 = true;
Console.WriteLine("FortranLoopMethodState.Goto2");
outGoto2 = loopI + param2;
goto goto1;
end:
DoNothing(); // We don't use break, do we?
}
Console.WriteLine("DoAfterLoop");
outAfter = param1 - param2;
Console.WriteLine(outGoto1);
Console.WriteLine(outGoto2);
}
Converted method:
public class ExecuteFortranMethod
{
private enum FortranLoopMethodState
{
LoopCycleStart,
Goto1,
Goto2,
LoopCycleEnded
}
#region Params
private Int32 param1;
private Int32 param2;
#endregion
#region Variables
public Int32 loopI;
public Int32 outBefore,
outAfter,
outGoto1,
outGoto2;
public Int32[] outValues = new Int32[7];
#endregion
#region Constructors
public ExecuteFortranMethod(Int32 param1, Int32 param2)
{
this.param1 = param1;
this.param2 = param2;
this.Invoke();
}
#endregion
#region Methods
private void Invoke()
{
Console.WriteLine("STATE MACHINE CLASS:");
this.DoBeforeLoop();
for (this.loopI = 0; this.loopI < 7; this.loopI++)
{
Console.WriteLine("Iteration {0}", this.loopI);
var state = FortranLoopMethodState.LoopCycleStart;
do
{
state = DoLoop(state);
}
while (state != FortranLoopMethodState.LoopCycleEnded);
}
this.DoAfterLoop();
}
#endregion
#region "Method" body methods
private void DoBeforeLoop()
{
Console.WriteLine("DoBeforeLoop");
this.outBefore = this.param1 + this.param2;
}
private void DoAfterLoop()
{
Console.WriteLine("DoAfterLoop");
this.outAfter = this.param1 - this.param2;
}
Boolean wasInGoto2;
private FortranLoopMethodState DoLoop(FortranLoopMethodState state)
{
switch (state)
{
case FortranLoopMethodState.LoopCycleStart:
{
Console.WriteLine("FortranLoopMethodState.LoopCycleStart");
this.outValues[this.loopI] = this.loopI;
return FortranLoopMethodState.Goto1;
}
case FortranLoopMethodState.Goto1:
{
Console.WriteLine("FortranLoopMethodState.Goto1");
this.outGoto1 = this.loopI + this.param1;
if (this.wasInGoto2)
{
this.wasInGoto2 = false;
return FortranLoopMethodState.LoopCycleEnded;
}
return FortranLoopMethodState.Goto2;
}
case FortranLoopMethodState.Goto2:
{
this.wasInGoto2 = true;
Console.WriteLine("FortranLoopMethodState.Goto2");
this.outGoto2 = this.loopI + this.param2;
return FortranLoopMethodState.Goto1;
}
default:
throw new InvalidOperationException("The state is invalid");
}
}
#endregion
}
Program.cs
Do(10, 20);
Console.WriteLine();
var result = new ExecuteFortranMethod(10, 20);
Console.WriteLine(result.outGoto1);
Console.WriteLine(result.outGoto2);
Console.WriteLine("Press any key");
Console.ReadKey(true);
As you can see the outputs are equivalent. I won't describe exactly how you can transfer the actual method, because it is a tedious (but not unreal) task with no real shortcuts and most of the ideas will be clear when you read even this tiny example.
P.S.1: While there are no real shortucts (except of course of writing some small tool that can generate such state machine classes for the given code), you may simplify the manual job with a bit of regular expressions search and replace (Ctrl+F). For example, replacing pattern goto(\d+) with case State.Goto$1 { will replace all gotos with switch case stubs.
P.S.2: If there are far too many switch cases(gotos) you may want to replace switch with some Dictionary lookup.
P.S.3: And as many have already pointed it, I'd still recommend you to try to understand the original code flow and to rewrite it from scratch.
A goto inside the loop means two things:
stop the current execution of the loop (that's like using continue)
skip everything before the goto label (that's like using an if)
Instead of if-statements you could theoretically use a big switch statement without breaks on each case (fall through mode), so instead of doing a goto you can just set the switch value (create a variable) to the correct position and then call continue.
But that would be the same logic and lead to the same problems that you have when using gotos. It is not understandable, debuggable, maintainable for someone who didn't write the code. After 3-4 months it is even hard for the same person.
As a first step you should try to take each block and identify what exactly it does and if possible extract it to a method/function with a good name.
When your finished you hopefully have a huge goto mess with some function calls in it. Try to reduce the mess with if statements. g70 looks like a probable candidate because it conditionaly performs the g80 stuff or skips it and continues at g90, but haven't looked in detail at it.
Once you have it down to that level, you can also make execution graphs, one row (maybe in a spreadsheet) for each goto label and just write down which functions then get called until it reaches another goto.
Basic for a good refactoring is a good understanding of the problem, so maybe interviewing the person who wrote the pascal code to explain what it does can help you a lot.
Would be fun to see what you made out of the code once it's done and what it really does!
I've been searching for a while now (here and on google obviously) for a neat way to convert a set of UTM coordinates to Latitude and Longitude. I've got the coordinates and I know in what zone they are, but how do I convert this to Latitude and Longitude? I Was hoping there would be some kind of class that could do at least some of the magic for me, but it doesn't seem so :(
Any suggestions on this?
I know it can be done, as this converter seems to work just fine Geographic/UTM Coordinate Converter.
Any input is greatly appreciated! :)
Thanks!
Here is:
public static void ToLatLon(double utmX, double utmY, string utmZone, out double latitude, out double longitude)
{
bool isNorthHemisphere = utmZone.Last() >= 'N';
var diflat = -0.00066286966871111111111111111111111111;
var diflon = -0.0003868060578;
var zone = int.Parse(utmZone.Remove(utmZone.Length - 1));
var c_sa = 6378137.000000;
var c_sb = 6356752.314245;
var e2 = Math.Pow((Math.Pow(c_sa,2) - Math.Pow(c_sb,2)),0.5)/c_sb;
var e2cuadrada = Math.Pow(e2,2);
var c = Math.Pow(c_sa,2) / c_sb;
var x = utmX - 500000;
var y = isNorthHemisphere ? utmY : utmY - 10000000;
var s = ((zone * 6.0) - 183.0);
var lat = y / (c_sa * 0.9996);
var v = (c / Math.Pow(1 + (e2cuadrada * Math.Pow(Math.Cos(lat), 2)), 0.5)) * 0.9996;
var a = x / v;
var a1 = Math.Sin(2 * lat);
var a2 = a1 * Math.Pow((Math.Cos(lat)), 2);
var j2 = lat + (a1 / 2.0);
var j4 = ((3 * j2) + a2) / 4.0;
var j6 = ((5 * j4) + Math.Pow(a2 * (Math.Cos(lat)), 2)) / 3.0;
var alfa = (3.0 / 4.0) * e2cuadrada;
var beta = (5.0 / 3.0) * Math.Pow(alfa, 2);
var gama = (35.0 / 27.0) * Math.Pow(alfa, 3);
var bm = 0.9996 * c * (lat - alfa * j2 + beta * j4 - gama * j6);
var b = (y - bm) / v;
var epsi = ((e2cuadrada * Math.Pow(a, 2)) / 2.0) * Math.Pow((Math.Cos(lat)), 2);
var eps = a * (1 - (epsi / 3.0));
var nab = (b * (1 - epsi)) + lat;
var senoheps = (Math.Exp(eps) - Math.Exp(-eps)) / 2.0;
var delt = Math.Atan(senoheps/(Math.Cos(nab) ) );
var tao = Math.Atan(Math.Cos(delt) * Math.Tan(nab));
longitude = ((delt * (180.0 / Math.PI)) + s) + diflon;
latitude = ((lat + (1 + e2cuadrada * Math.Pow(Math.Cos(lat), 2) - (3.0 / 2.0) * e2cuadrada * Math.Sin(lat) * Math.Cos(lat) * (tao - lat)) * (tao - lat)) * (180.0 / Math.PI)) + diflat;
}
Take a look at this .NET library http://projnet.codeplex.com/ . This should help in your case
There is c++ code available on this website:
http://www.gpsy.com/gpsinfo/geotoutm/
Go down the page a bit to the "Source Code" heading, and look for these files at the bottom:
Chuck Gantz
Enclosures: LatLong-UTMconversion.cpp (view online as text file)
LatLong-UTMconversion.h (view online as text file)
UTMConversions.cpp (view online as text file)
SwissGrid.cpp (view online as text file)
constants.h (view online as text file)
e.g. the first file links to:
www.gpsy.com/gpsinfo/geotoutm/gantz/LatLong-UTMconversion.cpp
etc
There are functions here for going both ways: UTM to Lat Long, and vice versa.
If you look elsewhere, there are python versions of this code.
e.g.
at code.google.com/p/pys60gps/source/browse/trunk/lib/LatLongUTMconversion.py?r=246
There are also c# versions of some of it:
at mediakey.dk/~cc/convert-northing-and-easting-utm-to-longitude-and-latitude/
Good luck.
I made a port from a javascript library to C#, I have tested it and works perfectly, you can take a look at it here.
Checkout CoordinateSharp on NuGet. It's really easy to do this with it.
//Example
UniversalTransverseMercator utm = new UniversalTransverseMercator("Q", 14, 581943.5, 2111989.8);
Coordinate c = UniversalTransverseMercator.ConvertUTMtoLatLong(utm);
Use this code:
public static void UTMToLatLon(double Easting, double Northing, double Zone, double Hemi, out double latitude, out double longitude)
{
double DtoR = Math.PI / 180, RtoD = 180 / Math.PI;
double a = 6378137, f = 0.00335281066474748071984552861852, northernN0 = 0, southernN0 = 10000000, E0 = 500000,
n = f / (2 - f), k0 = 0.9996,
A = a * (1 + (1 / 4) * Math.Pow(n, 2) + (1 / 64) * Math.Pow(n, 4) + (1 / 256) * Math.Pow(n, 6) + (25 / 16384) * Math.Pow(n, 8) + (49 / 65536) * Math.Pow(n, 10)) / (1 + n),
beta1 = n / 2 - (2 / 3) * Math.Pow(n, 2) + (37 / 96) * Math.Pow(n, 3) - (1 / 360) * Math.Pow(n, 4) - (81 / 512) * Math.Pow(n, 5) + (96199 / 604800) * Math.Pow(n, 6) - (5406467 / 38707200) * Math.Pow(n, 7) + (7944359 / 67737600) * Math.Pow(n, 8) - (7378753979 / 97542144000) * Math.Pow(n, 9) + (25123531261 / 804722688000) * Math.Pow(n, 10),
beta2 = (1 / 48) * Math.Pow(n, 2) + (1 / 15) * Math.Pow(n, 3) - (437 / 1440) * Math.Pow(n, 4) + (46 / 105) * Math.Pow(n, 5) - (1118711 / 3870720) * Math.Pow(n, 6) + (51841 / 1209600) * Math.Pow(n, 7) + (24749483 / 348364800) * Math.Pow(n, 8) - (115295683 / 1397088000) * Math.Pow(n, 9) + (5487737251099 / 51502252032000) * Math.Pow(n, 10),
beta3 = (17 / 480) * Math.Pow(n, 3) - (37 / 840) * Math.Pow(n, 4) - (209 / 4480) * Math.Pow(n, 5) + (5569 / 90720) * Math.Pow(n, 6) + (9261899 / 58060800) * Math.Pow(n, 7) - (6457463 / 17740800) * Math.Pow(n, 8) + (2473691167 / 9289728000) * Math.Pow(n, 9) - (852549456029 / 20922789888000) * Math.Pow(n, 10),
beta4 = (4397 / 161280) * Math.Pow(n, 4) - (11 / 504) * Math.Pow(n, 5) - (830251 / 7257600) * Math.Pow(n, 6) + (466511 / 2494800) * Math.Pow(n, 7) + (324154477 / 7664025600) * Math.Pow(n, 8) - (937932223 / 3891888000) * Math.Pow(n, 9) - (89112264211 / 5230697472000) * Math.Pow(n, 10),
beta5 = (4583 / 161280) * Math.Pow(n, 5) - (108847 / 3991680) * Math.Pow(n, 6) - (8005831 / 63866880) * Math.Pow(n, 7) + (22894433 / 124540416) * Math.Pow(n, 8) + (112731569449 / 557941063680) * Math.Pow(n, 9) - (5391039814733 / 10461394944000) * Math.Pow(n, 10),
beta6 = (20648693 / 638668800) * Math.Pow(n, 6) - (16363163 / 518918400) * Math.Pow(n, 7) - (2204645983 / 12915302400) * Math.Pow(n, 8) + (4543317553 / 18162144000) * Math.Pow(n, 9) + (54894890298749 / 167382319104000) * Math.Pow(n, 10),
beta7 = (219941297 / 5535129600) * Math.Pow(n, 7) - (497323811 / 12454041600) * Math.Pow(n, 8) - (79431132943 / 332107776000) * Math.Pow(n, 9) + (4346429528407 / 12703122432000) * Math.Pow(n, 10),
beta8 = (191773887257 / 3719607091200) * Math.Pow(n, 8) - (17822319343 / 336825216000) * Math.Pow(n, 9) - (497155444501631 / 1422749712384000) * Math.Pow(n, 10),
beta9 = (11025641854267 / 158083301376000) * Math.Pow(n, 9) - (492293158444691 / 6758061133824000) * Math.Pow(n, 10),
beta10 = (7028504530429621 / 72085985427456000) * Math.Pow(n, 10),
delta1 = 2 * n - (2 / 3) * Math.Pow(n, 2) - 2 * Math.Pow(n, 3),
delta2 = (7 / 3) * Math.Pow(n, 2) - (8 / 5) * Math.Pow(n, 3),
delta3 = (56 / 15) * Math.Pow(n, 3),
ksi = (Northing / 100 - northernN0) / (k0 * A), eta = (Easting / 100 - E0) / (k0 * A),
ksi_prime = ksi - (beta1 * Math.Sin(2 * ksi) * Math.Cosh(2 * eta) + beta2 * Math.Sin(4 * ksi) * Math.Cosh(4 * eta) + beta3 * Math.Sin(6 * ksi) * Math.Cosh(6 * eta) + beta4 * Math.Sin(8 * ksi) * Math.Cosh(8 * eta) + beta5 * Math.Sin(10 * ksi) * Math.Cosh(10 * eta) +
beta6 * Math.Sin(12 * ksi) * Math.Cosh(12 * eta) + beta7 * Math.Sin(14 * ksi) * Math.Cosh(14 * eta) + beta8 * Math.Sin(16 * ksi) * Math.Cosh(16 * eta) + beta9 * Math.Sin(18 * ksi) * Math.Cosh(18 * eta) + beta10 * Math.Sin(20 * ksi) * Math.Cosh(20 * eta)),
eta_prime = eta - (beta1 * Math.Cos(2 * ksi) * Math.Sinh(2 * eta) + beta2 * Math.Cos(4 * ksi) * Math.Sinh(4 * eta) + beta3 * Math.Cos(6 * ksi) * Math.Sinh(6 * eta)),
sigma_prime = 1 - (2 * beta1 * Math.Cos(2 * ksi) * Math.Cosh(2 * eta) + 2 * beta2 * Math.Cos(4 * ksi) * Math.Cosh(4 * eta) + 2 * beta3 * Math.Cos(6 * ksi) * Math.Cosh(6 * eta)),
taw_prime = 2 * beta1 * Math.Sin(2 * ksi) * Math.Sinh(2 * eta) + 2 * beta2 * Math.Sin(4 * ksi) * Math.Sinh(4 * eta) + 2 * beta3 * Math.Sin(6 * ksi) * Math.Sinh(6 * eta),
ki = Math.Asin(Math.Sin(ksi_prime) / Math.Cosh(eta_prime));
latitude = (ki + delta1 * Math.Sin(2 * ki) + delta2 * Math.Sin(4 * ki) + delta3 * Math.Sin(6 * ki)) * RtoD;
double longitude0 = Zone * 6 * DtoR - 183 * DtoR ;
longitude = (longitude0 + Math.Atan(Math.Sinh(eta_prime) / Math.Cos(ksi_prime))) * RtoD;
}
This code is far more Accurate than others.