Horizontal sundial calculations: Difference between revisions
Content added Content deleted
(→{{header|Kotlin}}: Updated example see https://github.com/dkandalov/rosettacode-kotlin for details) |
m (→{{header|REXX}}: added/changed wording in the REXX section header, added/changed comments and whitespace, optimized the ATAN function.) |
||
Line 2,030: | Line 2,030: | ||
=={{header|REXX}}== |
=={{header|REXX}}== |
||
REXX doesn't have the usual |
The REXX language doesn't have the usual trigonometric functions, nor for that matter, a '''sqrt''' (square root) function, |
||
<br>so these as well as '''pi''' were added to this program. |
|||
No attempt was made to explain the inner workings of the trigonometric functions. |
No attempt was made to explain the inner workings of the trigonometric functions. |
||
<lang rexx>/*REXX program displays: hour, sun hour angle, dial hour line angle, 6am ───► 6pm. */ |
<lang rexx>/*REXX program displays: hour, sun hour angle, dial hour line angle, 6am ───► 6pm. */ |
||
numeric digits 60 /* |
numeric digits 60 /*in case sundial is in polar regions. */ |
||
parse arg lat lng mer . /*obtain optional arguments from the CL*/ |
parse arg lat lng mer . /*obtain optional arguments from the CL*/ |
||
/* ┌───────────◄ None specified? Then use the default*/ |
/* ┌───────────◄ None specified? Then use the default*/ |
||
Line 2,042: | Line 2,043: | ||
if lng=='' | lng=="," then lng= -150.5 /* " " " " " " */ |
if lng=='' | lng=="," then lng= -150.5 /* " " " " " " */ |
||
if mer=='' | mer=="," then mer= -150 /* " " " " " " */ |
if mer=='' | mer=="," then mer= -150 /* " " " " " " */ |
||
⚫ | |||
⚫ | |||
⚫ | |||
say ' legal meridian:' right(mer, L) /* " legal meridian " " " */ |
|||
sineLat=sin( d2r(lat) ) /*calculate sine of (radian) latitude. */ |
sineLat=sin( d2r(lat) ) /*calculate sine of (radian) latitude. */ |
||
w1=max(length('hour' |
w1=max( length('hour' ), length("midnight" )) + 2 /*compute the max hour width.*/ |
||
w2=max(length('sun hour' |
w2=max( length('sun hour' ), length("angle" )) + 2 /* " " " angle " */ |
||
w3=max(length('dial hour'), length("line angle")) + 2 |
w3=max( length('dial hour'), length("line angle")) + 2 /* " " " lineº " */ |
||
⚫ | |||
indent=left('', 30) /*make the presentation a bit prettier.*/ |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
say ' legal meridian:' right(mer, L) /* " legal meridian " " " */ |
|||
indent=left('', 30) /*make prettier: indented presentation.*/ |
|||
⚫ | |||
⚫ | |||
call sep /*to help a one-eyed pirate's eyeball. */ |
|||
do h=-6 to 6 /*Okey dokey then, now let's show stuff*/ |
|||
select |
select |
||
when abs(h)==12 then hc='midnight' /*Holy smokes! Above the arctic circle.*/ |
when abs(h)==12 then hc='midnight' /*Holy smokes! Above the arctic circle.*/ |
||
when h <0 then hc=-h 'am' |
when h <0 then hc= -h 'am' /*convert da hour for human beans (sic)*/ |
||
when h==0 then hc='noon' /* ··· easier to understand now. */ |
when h==0 then hc='noon' /* ··· easier to understand now. */ |
||
when h >0 then hc=h 'pm' |
when h >0 then hc= h 'pm' /* ··· even more meaningful. */ |
||
end /*select*/ |
end /*select*/ |
||
hra=15 * h - lng + mer /*calculate sun hour angle (in degrees)*/ |
hra=15 * h - lng + mer /*calculate sun hour angle (in degrees)*/ |
||
hla=r2d(Atan(sineLat * tan( d2r(hra)))) |
hla=r2d( Atan(sineLat * tan( d2r(hra)))) /*this is the heavy lifting calculation*/ |
||
say indent center(hc, w1) right(format(hra, ,1), w2) right(format(hla, ,1), w3) |
say indent center(hc, w1) right(format(hra, ,1), w2) right(format(hla, ,1), w3) |
||
end /*h*/ |
end /*h*/ |
||
call sep /*to help a one-eyed pirate's eyeball. */ |
|||
call sep |
|||
exit /*stick a fork in it, we're all done. */ |
exit /*stick a fork in it, we're all done. */ |
||
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
||
Line 2,073: | Line 2,074: | ||
r2d: return d2d( (arg(1) * 180 / pi() ) ) /*convert radians ──► degrees. */ |
r2d: return d2d( (arg(1) * 180 / pi() ) ) /*convert radians ──► degrees. */ |
||
r2r: return arg(1) //(pi() * 2) /*normalize radians ──► a unit circle. */ |
r2r: return arg(1) //(pi() * 2) /*normalize radians ──► a unit circle. */ |
||
sep: say indent copies('═', w1) copies("═",w2) copies('═',w3); |
sep: say indent copies('═', w1) copies("═", w2) copies('═', w3); return |
||
tan: procedure; parse arg x; _=cos(x); if _=0 then call tanErr; return sin(x)/_ |
tan: procedure; parse arg x; _=cos(x); if _=0 then call tanErr; return sin(x)/_ |
||
tellErr: say; say '*** error ***'; say; say arg(1); say; exit 13 |
tellErr: say; say '*** error ***'; say; say arg(1); say; exit 13 |
||
Line 2,080: | Line 2,081: | ||
tanErr: call tellErr 'tan(' || x") causes division by zero, X=" x |
tanErr: call tellErr 'tan(' || x") causes division by zero, X=" x |
||
Acos: procedure; arg x; if x<-1 | x>1 then call AcosErr; return .5 * pi() - Asin(x) |
Acos: procedure; arg x; if x<-1 | x>1 then call AcosErr; return .5 * pi() - Asin(x) |
||
Atan: procedure; parse arg x; if abs(x)=1 then return pi()/4*x; return Asin(x/sqrt(1+x*x)) |
|||
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
||
Asin: procedure; |
Asin: procedure; parse arg x; if x<-1 | x>1 then call AsinErr; s=x*x |
||
if abs(x)>=sqrt(2)*.4 then return sign(x) * Acos(sqrt(1-s)); z=x; o=x; p=z |
if abs(x)>=sqrt(2)*.4 then return sign(x) * Acos(sqrt(1-s)); z=x; o=x; p=z |
||
do j=2 by 2; o=o*s*(j-1)/j; z=z+o/(j+1); if z=p then leave; p=z; end; return z |
do j=2 by 2; o=o*s*(j-1)/j; z=z+o/(j+1); if z=p then leave; p=z; end; return z |
||
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
||
sin: procedure; parse arg x; x=r2r(x); numeric fuzz min(5, digits() - 3) |
|||
if abs(x)=pi() then return ; return .sinCos(x,x,1) |
|||
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
|||
sin: procedure; arg x; x=r2r(x); numeric fuzz min(5, digits() - 3) |
|||
if abs(x)=pi() then return 0; return .sinCos(x,x,1) |
|||
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
||
cos: procedure; parse arg x; x=r2r(x); a=abs(x); hpi=pi*.5 |
cos: procedure; parse arg x; x=r2r(x); a=abs(x); hpi=pi*.5 |
||
Line 2,096: | Line 2,095: | ||
if a=pi() * 2 / 3 then return -.5; return .sinCos(1,1,-1) |
if a=pi() * 2 / 3 then return -.5; return .sinCos(1,1,-1) |
||
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
||
.sinCos: parse arg z,_,i; x=x*x; |
.sinCos: parse arg z,_,i; x=x*x; p=z |
||
do k=2 by 2; _= -_ |
do k=2 by 2; _= -_*x/(k*(k+i)); z=z+_; if z=p then leave; p=z; end; return z |
||
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
||
sqrt: procedure; parse arg x; if x=0 then return 0; d=digits(); numeric digits; h=d+6 |
sqrt: procedure; parse arg x; if x=0 then return 0; d=digits(); numeric digits; h=d+6 |