Horizontal sundial calculations: Difference between revisions
→{{header|AutoHotkey}}: marked incorrect (6AM,5AM..1AM,0PM) |
m →{{header|Phix}}: added syntax colouring, marked p2js compatible |
||
Line 2,169:
=={{header|Phix}}==
For better behaviour/proper input on pwa/p2js I suppose this should really be a pGUI app.
<!--<lang Phix>(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">prompt</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">text</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Enter %s (%g):"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">text</span><span style="color: #0000FF;">,</span><span style="color: #000000;">v</span><span style="color: #0000FF;">})</span>
<span style="color: #004080;">object</span> <span style="color: #000000;">answer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">gets</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">'\n'</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #004080;">string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">answer</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">to_number</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">trim</span><span style="color: #0000FF;">(</span><span style="color: #000000;">answer</span><span style="color: #0000FF;">),</span><span style="color: #000000;">v</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">else</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s:%g\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">text</span><span style="color: #0000FF;">,</span><span style="color: #000000;">v</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">v</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">deg2rad</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">PI</span><span style="color: #0000FF;">/</span><span style="color: #000000;">180</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">rad2deg</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">180</span><span style="color: #0000FF;">/</span><span style="color: #004600;">PI</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">lat</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">prompt</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Latitude"</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">4.95</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">lng</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">prompt</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Longitude"</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">150.5</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">mer</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">prompt</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Legal Meridian"</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">150</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">slat</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lat</span><span style="color: #0000FF;">*</span><span style="color: #000000;">deg2rad</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"""
Sine of latitude: %g
Longitude offset: %g
Hour Sun hour angle Dial hour line angle
-------- -------------- --------------------
"""</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">slat</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lng</span><span style="color: #0000FF;">-</span><span style="color: #000000;">mer</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">hour</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">6</span> <span style="color: #008080;">to</span> <span style="color: #000000;">6</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">ha</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">hour</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">15</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">lng</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">mer</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ha</span><span style="color: #0000FF;">*</span><span style="color: #000000;">deg2rad</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cos</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ha</span><span style="color: #0000FF;">*</span><span style="color: #000000;">deg2rad</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">hla</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">atan2</span><span style="color: #0000FF;">(</span><span style="color: #000000;">slat</span><span style="color: #0000FF;">*</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">rad2deg</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">hour12</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hour</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">?</span><span style="color: #000000;">hour</span><span style="color: #0000FF;">+</span><span style="color: #000000;">12</span><span style="color: #0000FF;">:</span><span style="color: #000000;">hour</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">am</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hour</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span><span style="color: #0000FF;">?</span><span style="color: #008000;">"am"</span><span style="color: #0000FF;">:</span><span style="color: #008000;">"pm"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%3d:00%s %12.3f %17.3f\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">hour12</span><span style="color: #0000FF;">,</span><span style="color: #000000;">am</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ha</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hla</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</lang>-->
{{out}}
<pre>
Enter Latitude
Enter Longitude
Enter Legal Meridian
Sine of latitude: -0.086286
Longitude offset: -0.5
Hour
-------- -------------- --------------------
6 -89.500 84.225▼
</pre>
|
Revision as of 15:49, 19 January 2022
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
- Task
Create a program that calculates the hour, sun hour angle, dial hour line angle from 6am to 6pm for an operator entered location.
For example, the user is prompted for a location and inputs the latitude and longitude 4°57′S 150°30′W (4.95°S 150.5°W of Jules Verne's Lincoln Island, aka Ernest Legouve Reef), with a legal meridian of 150°W.
(Note: the "meridian" is approximately the same concept as the "longitude" - the distinction is that the meridian is used to determine when it is "noon" for official purposes. This will typically be slightly different from when the sun appears at its highest location, because of the structure of time zones. For most, but not all, time zones (hour wide zones with hour zero centred on Greenwich), the legal meridian will be an even multiple of 15 degrees.)
Wikipedia: A sundial is a device that measures time by the position of the Sun. In common designs such as the horizontal sundial, the sun casts a shadow from its style (also called its Gnomon, a thin rod or a sharp, straight edge) onto a flat surface marked with lines indicating the hours of the day (also called the dial face or dial plate). As the sun moves across the sky, the shadow-edge progressively aligns with different hour-lines on the plate. Such designs rely on the style being aligned with the axis of the Earth's rotation. Hence, if such a sundial is to tell the correct time, the style must point towards true north (not the north or south magnetic pole) and the style's angle with horizontal must equal the sundial's geographical latitude.
11l
<lang 11l>V lat = Float(input(‘Enter latitude => ’)) V lng = Float(input(‘Enter longitude => ’)) V ref = Float(input(‘Enter legal meridian => ’)) print()
V slat = sin(radians(lat)) print(‘ sine of latitude: #.3’.format(slat)) print(‘ diff longitude: #.3’.format(lng - ref)) print() print(‘Hour, sun hour angle, dial hour line angle from 6am to 6pm’)
L(h) -6 .. 6
V hra = 15.0 * h hra -= lng - ref V hla = degrees(atan(slat * tan(radians(hra)))) print(‘HR=#3; HRA=#3.3; HLA=#3.3’.format(h, hra, hla))</lang>
- Output:
Enter latitude => -4.95 Enter longitude => -150.5 Enter legal meridian => -150 sine of latitude: -0.086 diff longitude: -0.500 Hour, sun hour angle, dial hour line angle from 6am to 6pm HR= -6; HRA=-89.500; HLA= 84.225 HR= -5; HRA=-74.500; HLA= 17.283 HR= -4; HRA=-59.500; HLA= 8.334 HR= -3; HRA=-44.500; HLA= 4.847 HR= -2; HRA=-29.500; HLA= 2.795 HR= -1; HRA=-14.500; HLA= 1.278 HR= 0; HRA= 0.500; HLA= -0.043 HR= 1; HRA= 15.500; HLA= -1.371 HR= 2; HRA= 30.500; HLA= -2.910 HR= 3; HRA= 45.500; HLA= -5.018 HR= 4; HRA= 60.500; HLA= -8.671 HR= 5; HRA= 75.500; HLA=-18.451 HR= 6; HRA= 90.500; HLA= 84.225
Ada
sundial.adb: <lang Ada>with Ada.Text_IO; with Ada.Numerics.Elementary_Functions; procedure Sundial is
use Ada.Numerics.Elementary_Functions; use Ada.Numerics; package Float_IO is new Ada.Text_IO.Float_IO (Float);
Latitude, Longitude, Meridian : Float; Latitude_Sine : Float;
begin
Ada.Text_IO.Put ("Enter latitude: "); Float_IO.Get (Latitude); Ada.Text_IO.Put ("Enter longitude: "); Float_IO.Get (Longitude); Ada.Text_IO.Put ("Enter legal meridian: "); Float_IO.Get (Meridian); Ada.Text_IO.New_Line;
Latitude_Sine := Sin (Latitude * Pi / 180.0); Ada.Text_IO.Put_Line (" sine of latitude:" & Float'Image (Latitude_Sine)); Ada.Text_IO.Put_Line (" diff longitude:" & Float'Image (Longitude - Meridian)); Ada.Text_IO.New_Line;
Ada.Text_IO.Put_Line ("hour, sun hour angle, dial hour line angle from 6am to 6pm"); for H in -6 .. 6 loop declare Hour_Angle : constant Float := 15.0 * Float (H) - (Longitude - Meridian); Line_Angle : constant Float := Arctan (Latitude_Sine * Tan (Hour_Angle * Pi / 180.0)) * 180.0 / Pi; begin Ada.Text_IO.Put_Line ("HR=" & Integer'Image (H) & "; HRA=" & Float'Image (Hour_Angle) & "; HLA=" & Float'Image (Line_Angle)); end; end loop;
end Sundial;</lang>
- Output:
Enter latitude: -4.95 Enter longitude: -150.5 Enter legal meridian: -150 sine of latitude:-8.62864E-02 diff longitude:-5.00000E-01 hour, sun hour angle, dial hour line angle from 6am to 6pm HR=-6; HRA=-8.95000E+01; HLA= 8.42248E+01 HR=-5; HRA=-7.45000E+01; HLA= 1.72829E+01 HR=-4; HRA=-5.95000E+01; HLA= 8.33371E+00 HR=-3; HRA=-4.45000E+01; HLA= 4.84671E+00 HR=-2; HRA=-2.95000E+01; HLA= 2.79487E+00 HR=-1; HRA=-1.45000E+01; HLA= 1.27835E+00 HR= 0; HRA= 5.00000E-01; HLA=-4.31443E-02 HR= 1; HRA= 1.55000E+01; HLA=-1.37079E+00 HR= 2; HRA= 3.05000E+01; HLA=-2.90964E+00 HR= 3; HRA= 4.55000E+01; HLA=-5.01802E+00 HR= 4; HRA= 6.05000E+01; HLA=-8.67140E+00 HR= 5; HRA= 7.55000E+01; HLA=-1.84510E+01 HR= 6; HRA= 9.05000E+01; HLA= 8.42248E+01
ALGOL 68
Example extracted - with permission for a GPL - from Simon Wheaton-Smith's Illustrating Time's Shadow web page. <lang algol68>BEGIN
REAL lat, slat, lng, ref; print ( "Enter latitude => " ); read (lat); print ( "Enter longitude => " ); read (lng); print ( "Enter legal meridian => " ); read (ref); new line(stand out);
slat := sin(lat*2*pi/360) ; print ( (" sine of latitude: ", float(slat,8,2,1), new line ) ); print ( (" diff longitude: ", fixed((lng - ref),0,3), new line, new line ) );
print ( ("Hour, sun hour angle, dial hour line angle from 6am to 6pm", new line ));
FOR h FROM -6 TO 6 DO REAL hra , hla ; # define hour angle and hour line angle # hra := 15 * h ; # hour angle is 15 times the hour # hra := hra - (lng - ref); # but correct for longitude difference # hla := arc tan ( slat * tan(hra*2*pi/360) ) * 360 / ( 2*pi) ; # page 132 of a68gdoc.pdf documentationfile # print ("HR="+whole(h,3)+"; HRA="+fixed(hra,8,3)+"; HLA="+fixed(hla,8,3)); new line(stand out) OD
END</lang>
- Output:
Enter latitude => -4.95 Enter longitude => -150.5 Enter legal meridian => -150 sine of latitude: -86.3e-3 diff longitude: -.500 Hour, sun hour angle, dial hour line angle from 6am to 6pm HR= -6; HRA= -89.500; HLA= +84.225 HR= -5; HRA= -74.500; HLA= +17.283 HR= -4; HRA= -59.500; HLA= +8.334 HR= -3; HRA= -44.500; HLA= +4.847 HR= -2; HRA= -29.500; HLA= +2.795 HR= -1; HRA= -14.500; HLA= +1.278 HR= +0; HRA= +0.500; HLA= -0.043 HR= +1; HRA= +15.500; HLA= -1.371 HR= +2; HRA= +30.500; HLA= -2.910 HR= +3; HRA= +45.500; HLA= -5.018 HR= +4; HRA= +60.500; HLA= -8.671 HR= +5; HRA= +75.500; HLA= -18.451 HR= +6; HRA= +90.500; HLA= +84.225
AutoHotkey
AutoHotkey is not a command-line programming language, let me make that clear. However, in translating the F# I found that the command line really is best for this type of app. The first 3 comments in the script describe the workarounds used to interface with the commandline. <lang AutoHotkey>DllCall("AllocConsole") ; Open a console window for this application Pi := 4*ATan(1) ,Degrees := Pi/180
FileAppend, Enter Latitude: , CONOUT$ ; write to stdout FileReadLine, latitude, CONIN$, 1 ; read from stdin
FileAppend, Enter Longitude: , CONOUT$ FileReadLine, longitude, CONIN$, 1
FileAppend, Enter Legal meridian: , CONOUT$ FileReadLine, meridian, CONIN$, 1
sineLatitude := Sin(latitude*Degrees) FileAppend, `n, CONOUT$ FileAppend, Sine of latitude: %sineLatitude%`n, CONOUT$ FileAppend, % "Difference of Longitudes (given longitude - meridian): " . longitude-meridian . "`n", CONOUT$ FileAppend, `n, CONOUT$
FileAppend, Numbers from 6 AM to 6 PM:`n, CONOUT$ FileAppend, Hour`t`tSun Hour Angle`t Dial hour line angle`n, CONOUT$
hour := -7
While (++hour < 7)
{
clockHour := hour < 0 ? abs(hour) . "AM" : hour . "PM" shr := RTrim("" . (15.0*hour - (longitude-meridian)), "0") ; RTrim() removes trailing zeroes dhla := Atan(sineLatitude*Tan(shr*degrees))/Degrees FileAppend, %clockhour%`t`t%shr%`t`t%dhla%`n, CONOUT$
} MsgBox close me when done.</lang>
- Output:
Enter Latitude:-4.95 Enter Longitude:-150.5 Enter Legal meridian:-150 Sine of latitude: -0.086286 Difference of Longitudes (given longitude - meridian): -0.500000 Numbers from 6 AM to 6 PM: Hour Sun Hour Angle Dial hour line angle 6AM -89.5 84.224833 5AM -74.5 17.282934 4AM -59.5 8.333712 3AM -44.5 4.846709 2AM -29.5 2.794874 1AM -14.5 1.278353 0PM 0.5 -0.043144 1PM 15.5 -1.370788 2PM 30.5 -2.909643 3PM 45.5 -5.018023 4PM 60.5 -8.671397 5PM 75.5 -18.450999 6PM 90.5 84.224833
AWK
<lang AWK>
- syntax: GAWK -f HORIZONTAL_SUNDIAL_CALCULATIONS.AWK
BEGIN {
printf("enter latitude (degrees): ") ; getline latitude printf("enter longitude (degrees): ") ; getline longitude printf("enter legal meridian (degrees): ") ; getline meridian printf("\nhour sun hour angle dial hour line angle\n") slat = sin(dr(latitude)) for (hour=-6; hour<=6; hour++) { # 6AM-6PM hra = 15 * hour - longitude + meridian hraRad = dr(hra) hla = rd(atan2(sin(hraRad)*slat,cos(hraRad))) printf("%4d %15.3f %21.3f\n",hour+12,hra,hla) } exit(0)
} function dr(x) { return x * 3.14159265 / 180 } # degrees to radians function rd(x) { return x * 180 / 3.14159265 } # radians to degrees </lang>
output:
enter latitude (degrees): -4.95 enter longitude (degrees): -150.5 enter legal meridian (degrees): -150 hour sun hour angle dial hour line angle 6 -89.500 84.225 7 -74.500 17.283 8 -59.500 8.334 9 -44.500 4.847 10 -29.500 2.795 11 -14.500 1.278 12 0.500 -0.043 13 15.500 -1.371 14 30.500 -2.910 15 45.500 -5.018 16 60.500 -8.671 17 75.500 -18.451 18 90.500 -95.775
BBC BASIC
<lang bbcbasic> INSTALL @lib$+"FNUSING"
INPUT "Enter latitude (degrees) : " latitude INPUT "Enter longitude (degrees) : " longitude INPUT "Enter legal meridian (degrees): " meridian PRINT '" Time", "Sun hour angle", "Dial hour line angle" FOR hour = 6 TO 18 hra = 15*hour - longitude + meridian - 180 hla = DEG(ATN(SIN(RAD(latitude)) * TAN(RAD(hra)))) IF ABS(hra) > 90 hla += 180 * SGN(hra * latitude) PRINT FNusing("##.##", hour), FNusing(" ####.### ", hra), FNusing(" ####.###", hla) NEXT hour</lang>
- Output:
(note the correct negative value for time 18:00)
Enter latitude (degrees) : -4.95 Enter longitude (degrees) : -150.5 Enter legal meridian (degrees): -150.0 Time Sun hour angle Dial hour line angle 6.00 -89.500 84.225 7.00 -74.500 17.283 8.00 -59.500 8.334 9.00 -44.500 4.847 10.00 -29.500 2.795 11.00 -14.500 1.278 12.00 0.500 -0.043 13.00 15.500 -1.371 14.00 30.500 -2.910 15.00 45.500 -5.018 16.00 60.500 -8.671 17.00 75.500 -18.451 18.00 90.500 -95.775
C
<lang c>#include <stdio.h>
- include <math.h>
- define PICKVALUE(TXT, VM) do { \
printf("%s: ", TXT); \ scanf("%lf", &VM); \ } while(0);
- if !defined(M_PI)
- define M_PI 3.14159265358979323846
- endif
- define DR(X) ((X)*M_PI/180.0)
- define RD(X) ((X)*180.0/M_PI)
int main() {
double lat, slat, lng, ref; int h; PICKVALUE("Enter latitude", lat); PICKVALUE("Enter longitude", lng); PICKVALUE("Enter legal meridian", ref); printf("\n");
slat = sin(DR(lat)); printf("sine of latitude: %.3f\n", slat); printf("diff longitude: %.3f\n\n", lng - ref); printf("Hour, sun hour angle, dial hour line angle from 6am to 6pm\n"); for(h = -6; h <= 6; h++) { double hla, hra; hra = 15.0*h; hra = hra - lng + ref; hla = RD(atan(slat * tan(DR(hra)))); printf("HR= %3d; \t HRA=%7.3f; \t HLA= %7.3f\n",
h, hra, hla);
}
return 0;
}</lang>
C#
<lang csharp>using System;
namespace RosettaCode {
internal sealed class Program { private static void Main() { Func<double> getDouble = () => Convert.ToDouble(Console.ReadLine()); double h = 0, lat, lng, lme, slat, hra, hla;
Console.Write("Enter latitude => "); lat = getDouble(); Console.Write("Enter longitude => "); lng = getDouble(); Console.Write("Enter legal meridian => "); lme = getDouble();
slat = Math.Sin(lat*2*Math.PI/360); Console.WriteLine("\n sine of latitude: {0:0.000}", slat); Console.WriteLine(" diff longitude: {0:0.000}\n", lng-lme); Console.WriteLine("Hour, sun hour angle, dial hour line angle from 6am to 6pm"); for (h = -6; h<6; h++) { hra = 15*h; hra -= lng-lme; hla = Math.Atan(slat*Math.Tan(hra*2*Math.PI/360))*360/(2*Math.PI); Console.WriteLine("HR= {0,7:0.000}; HRA {1,7:0.000}; HLA= {2,7:0.000}", h, hra, hla); } } }
}</lang>
C++
<lang cpp>#include <cmath>
- include <iostream>
- include <numbers>
// constants used in the calculations static const double DegreesPerHour = 15.0; static const double DegreesPerRadian = 180.0 * std::numbers::inv_pi;
// a structure for the calculation results struct SundialCalculation {
double HourAngle; double HourLineAngle;
};
// a class for a sundial at a location class Sundial {
// intermediate values used in the caclulations double m_sinLatitude; double m_timeZoneCorrection;
public:
Sundial(double latitude, double longitude, double legalMeridian) noexcept : m_sinLatitude(sin(latitude / DegreesPerRadian)) , m_timeZoneCorrection(legalMeridian - longitude) {}
SundialCalculation CalculateShadow(double hoursSinceNoon) const noexcept { double hourAngle = hoursSinceNoon * DegreesPerHour + m_timeZoneCorrection; double hourAngleRad = hourAngle / DegreesPerRadian; double hlaRad = atan2(m_sinLatitude * sin(hourAngleRad), cos(hourAngleRad)); double hourLineAngle = hlaRad * DegreesPerRadian; return SundialCalculation {hourAngle, hourLineAngle}; }
};
int main() {
double latitude, longitude, legalMeridian; std::cout << "Enter latitude:"; std::cin >> latitude; std::cout << "Enter longitude:"; std::cin >> longitude; std::cout << "Enter legal meridian:"; std::cin >> legalMeridian; // create a sundial at the user specified location const Sundial sundial(latitude, longitude, legalMeridian); for(int hour = -6; hour < 7; ++hour) { // cacluate the angles auto result = sundial.CalculateShadow(hour);
// print the results auto amOrPm = hour < 0 ? "am" : "pm"; auto hourString = std::to_string(hour < 1 ? 12 + hour : hour); std::cout << hourString << amOrPm << " - sun hour angle:" << result.HourAngle << ", dial hour line angle:" << result.HourLineAngle << "\n"; }
} </lang>
- Output:
Enter latitude:-4.95 Enter longitude:-150.5 Enter legal meridian:-150 6am - sun hour angle:-89.5, dial hour line angle:84.2248 7am - sun hour angle:-74.5, dial hour line angle:17.2829 8am - sun hour angle:-59.5, dial hour line angle:8.33371 9am - sun hour angle:-44.5, dial hour line angle:4.84671 10am - sun hour angle:-29.5, dial hour line angle:2.79487 11am - sun hour angle:-14.5, dial hour line angle:1.27835 12pm - sun hour angle:0.5, dial hour line angle:-0.0431443 1pm - sun hour angle:15.5, dial hour line angle:-1.37079 2pm - sun hour angle:30.5, dial hour line angle:-2.90964 3pm - sun hour angle:45.5, dial hour line angle:-5.01802 4pm - sun hour angle:60.5, dial hour line angle:-8.6714 5pm - sun hour angle:75.5, dial hour line angle:-18.451 6pm - sun hour angle:90.5, dial hour line angle:-95.7752
COBOL
<lang cobol>PROGRAM-ID. horizontal-sundial-calc.
DATA DIVISION. WORKING-STORAGE SECTION. 01 latitude PIC S9(3)V9(5) COMP. 01 longitude PIC S9(3)V9(5) COMP. 01 legal-meridian PIC S9(3)V9(5) COMP.
01 lat-sine PIC S9(3)V9(5) COMP. 01 diff-longitude PIC S9(3)V9(5) COMP.
01 lat-sine-disp PIC -(3)9.9(5). 01 diff-longitude-disp PIC -(3)9.9(5).
01 hour PIC S9 COMP. 01 sun-hour-angle PIC S9(3)V9(5) COMP. 01 dial-hour-line-angle PIC S9(3)V9(5) COMP.
01 hour-disp PIC 99. 01 sun-hour-angle-disp PIC -(3)9.9(5). 01 dial-hour-line-angle-disp PIC -(3)9.9(5).
PROCEDURE DIVISION.
DISPLAY "Enter latitude: " NO ADVANCING ACCEPT latitude DISPLAY "Enter longitude: " NO ADVANCING ACCEPT longitude DISPLAY "Enter legal meridian: " NO ADVANCING ACCEPT legal-meridian DISPLAY SPACE COMPUTE lat-sine, lat-sine-disp ROUNDED = FUNCTION SIN(latitude * 2 * FUNCTION PI / 360) DISPLAY "Sine of latitude: " FUNCTION TRIM(lat-sine-disp)
SUBTRACT legal-meridian FROM longitude GIVING diff-longitude, diff-longitude-disp DISPLAY "Diff longitude: " FUNCTION TRIM(diff-longitude-disp) DISPLAY SPACE
DISPLAY "Time Sun hour angle Dial hour line angle" PERFORM VARYING hour FROM -6 BY 1 UNTIL hour > 6 COMPUTE sun-hour-angle ROUNDED = hour * 15 - diff-longitude COMPUTE dial-hour-line-angle ROUNDED = FUNCTION ATAN(lat-sine * FUNCTION TAN(sun-hour-angle * 2 * FUNCTION PI / 360)) * 360 / (2 * FUNCTION PI)
ADD 12 TO hour GIVING hour-disp MOVE sun-hour-angle TO sun-hour-angle-disp MOVE dial-hour-line-angle TO dial-hour-line-angle-disp DISPLAY hour-disp ":00 " sun-hour-angle-disp " " dial-hour-line-angle-disp END-PERFORM .</lang>
- Output:
Enter latitude: -4.95 Enter longitude: -150.5 Enter legal meridian: -150 Sine of latitude: -0.08629 Diff longitude: -0.50000 Time Sun hour angle Dial hour line angle 06:00 -89.50000 84.22441 07:00 -74.50000 17.28173 08:00 -59.50000 8.33311 09:00 -44.50000 4.84635 10:00 -29.50000 2.79467 11:00 -14.50000 1.27826 12:00 0.50000 -0.04314 13:00 15.50000 -1.37069 14:00 30.50000 -2.90943 15:00 45.50000 -5.01765 16:00 60.50000 -8.67077 17:00 75.50000 -18.44973 18:00 90.50000 84.22441
D
<lang d>import std.stdio, std.math, std.conv, std.string;
double radians(in double x) pure nothrow { return x * (PI / 180); } double degrees(in double x) pure nothrow { return x / (PI / 180); }
T input(T)(in string msg) {
msg.write; return readln.strip.to!T;
}
void main() {
immutable lat = input!double("Enter latitude => "); immutable lng = input!double("Enter longitude => "); immutable lme = input!double("Enter legal meridian => "); writeln;
double slat = lat.radians.sin; writefln(" sine of latitude: %.3f", slat); writefln(" diff longitude: %.3f", lng - lme); writeln; "Hour, sun hour angle, dial hour line angle from 6am to 6pm".writeln;
foreach (immutable h; -6 .. 7) { immutable double hra = 15 * h - (lng - lme); immutable double hla = atan(slat * hra.radians.tan).degrees; writefln("HR=%3d; HRA=%7.3f; HLA=%7.3f", h, hra, hla); }
}</lang>
- Example run:
Enter latitude => -4.95 Enter longitude => -150.5 Enter legal meridian => -150 sine of latitude: -0.086 diff longitude: -0.500 Hour, sun hour angle, dial hour line angle from 6am to 6pm HR= -6; HRA=-89.500; HLA= 84.225 HR= -5; HRA=-74.500; HLA= 17.283 HR= -4; HRA=-59.500; HLA= 8.334 HR= -3; HRA=-44.500; HLA= 4.847 HR= -2; HRA=-29.500; HLA= 2.795 HR= -1; HRA=-14.500; HLA= 1.278 HR= 0; HRA= 0.500; HLA= -0.043 HR= 1; HRA= 15.500; HLA= -1.371 HR= 2; HRA= 30.500; HLA= -2.910 HR= 3; HRA= 45.500; HLA= -5.018 HR= 4; HRA= 60.500; HLA= -8.671 HR= 5; HRA= 75.500; HLA=-18.451 HR= 6; HRA= 90.500; HLA= 84.225
Delphi
See #Pascal
DWScript
<lang delphi>procedure PrintSundial(lat, lng, lme : Float); begin
PrintLn(Format('latitude: %7.2f', [lat])); PrintLn(Format('longitude: %7.2f', [lng])); PrintLn(Format('legal meridian: %7.2f', [lme]));
var slat := Sin(DegToRad(lat));
PrintLn(Format('sine of latitude: %.3f', [slat])); PrintLn(Format('diff longitude: %.3f', [lng-lme])); PrintLn(); PrintLn('Hour, sun hour angle, dial hour line angle from 6am to 6pm');
var h : Integer; for h:=-6 to 6 do begin var hra := 15 * h - (lng - lme); var hraRad := DegToRad(hra); var hla :=RadToDeg(ArcTan2(Sin(hraRad)*slat, Cos(hraRad))); PrintLn(Format('HR=%3d; HRA=%7.3f; HLA=%7.3f', [h, hra, hla])); end
end;
PrintSundial(-4.95, -150.5, -150);</lang>
- Output:
latitude: -4.95 longitude: -150.50 legal meridian: -150.00 sine of latitude: -0.086 diff longitude: -0.500 Hour, sun hour angle, dial hour line angle from 6am to 6pm HR= -6; HRA=-89.500; HLA= 84.225 HR= -5; HRA=-74.500; HLA= 17.283 HR= -4; HRA=-59.500; HLA= 8.334 HR= -3; HRA=-44.500; HLA= 4.847 HR= -2; HRA=-29.500; HLA= 2.795 HR= -1; HRA=-14.500; HLA= 1.278 HR= 0; HRA= 0.500; HLA= -0.043 HR= 1; HRA= 15.500; HLA= -1.371 HR= 2; HRA= 30.500; HLA= -2.910 HR= 3; HRA= 45.500; HLA= -5.018 HR= 4; HRA= 60.500; HLA= -8.671 HR= 5; HRA= 75.500; HLA=-18.451 HR= 6; HRA= 90.500; HLA=-95.775
EasyLang
<lang>func getn s$ . v .
write s$ v = number input print v
. call getn "Enter latitude: " lat call getn "Enter longitude: " lng call getn "Enter legal meridian: " merid slat = sin lat diff = lng - merid print "" print " sine of latitude: " & slat print " diff longitude: " & diff print "" print "Hour\tSun hour angle\tDial hour line angle" for h = -6 to 6
hra = 15 * h - diff hla = atan2 (slat * sin hra) cos hra print h + 12 & "\t" & hra & "\t\t" & hla
.</lang>
ERRE
<lang ERRE>PROGRAM SUN_DIAL
FUNCTION RAD(X)
RAD=X*π/180
END FUNCTION
FUNCTION DEG(X)
DEG=X*180/π
END FUNCTION
BEGIN
INPUT("Enter latitude (degrees) : ",latitude) INPUT("Enter longitude (degrees) : ",longitude) INPUT("Enter legal meridian (degrees): ",meridian)
PRINT PRINT(" Time Sun hour angle Dial hour line angle") PRINT("---------------------------------------------")
FOR HOUR=6 TO 18 DO HRA=15*HOUR-LONGITUDE+MERIDIAN-180 HLA=DEG(ATN(SIN(RAD(LATITUDE))*TAN(RAD(HRA)))) IF ABS(HRA)>90 THEN HLA+=180*SGN(HRA*LATITUDE) END IF WRITE("##.## ####.### ####.###";HOUR;HRA;HLA) END FOR
END PROGRAM </lang>
- Output:
Enter latitude (degrees) : ? -4.95 Enter longitude (degrees) : ? -150.5 Enter legal meridian (degrees): ? -150 Time Sun hour angle Dial hour line angle --------------------------------------------- 6.00 -89.500 84.225 7.00 -74.500 17.283 8.00 -59.500 8.334 9.00 -44.500 4.847 10.00 -29.500 2.795 11.00 -14.500 1.278 12.00 0.500 -0.043 13.00 15.500 -1.371 14.00 30.500 -2.910 15.00 45.500 -5.018 16.00 60.500 -8.671 17.00 75.500 -18.451 18.00 90.500 -95.775
Euphoria
<lang Euphoria> include std/console.e include std/mathcons.e
atom lat = prompt_number("Enter Latitude: ",{}) atom lng = prompt_number("Enter Longitude: ",{}) atom lm = prompt_number("Enter Legal Meridian: ",{}) puts(1,'\n')
atom ha, hla
function D2R(atom degrees) return degrees * PI / 180 end function
function R2D(atom radians) return radians * 180 / PI end function
function atan2(atom y, atom x) return 2*arctan((sqrt(power(x,2)+power(y,2)) - x)/y) end function
atom s_lat = sin(D2R(lat))
puts(1,"Hour, Sun Hour Angle, Dial Hour Line Angle\n")
for hour = -6 to 6 do ha = hour * 15 - lng + lm atom s = sin(D2R(ha)) atom c = cos(D2R(ha)) hla = R2D(atan2(s_lat*s,c)) printf(1,"%3d\t\t\t%7.3f\t\t\t%7.3f\n",{hour+12,ha,hla}) end for
if getc(0) then end if </lang>
- Output:
Enter Latitude: -4.95 Enter Longitude: -150.5 Enter Legal Meridian: -150 Hour, Sun Hour Angle, Dial Hour Line Angle 6 -89.500 84.225 7 -74.500 17.283 8 -59.500 8.334 9 -44.500 4.847 10 -29.500 2.795 11 -14.500 1.278 12 0.500 -0.043 13 15.500 -1.371 14 30.500 -2.910 15 45.500 -5.018 16 60.500 -8.671 17 75.500 -18.451 18 90.500 -95.775
F#
<lang fsharp>// Learn more about F# at http://fsharp.net
open System
//(degree measure)*Degrees => Radian measure //(radian measure)/Degrees => Degree measure let Degrees = Math.PI / 180.0
Console.Write("Enter latitude: ") let latitude = Console.ReadLine() |> Double.Parse
Console.Write("Enter longitude: ") let longitude = Console.ReadLine() |> Double.Parse
Console.Write("Enter legal meridian: ") let meridian = Console.ReadLine() |> Double.Parse
let sineLatitude = Math.Sin(latitude * Degrees) Console.WriteLine() Console.WriteLine("Sine of latitude: {0}",sineLatitude) Console.WriteLine("Difference of Longitudes (given longitude - meridian): {0}",longitude-meridian) Console.WriteLine()
printfn "Numbers from 6 AM to 6 PM: " printfn "Hour\t\tSun hour angle\t Dial hour line angle"
for hour in -6..6 do
let clockHour = if hour < 0 then String.Format("{0}AM",Math.Abs(hour)) else String.Format("{0}PM",hour) let shr = 15.0*(float)hour - (longitude - meridian) let dhla = Math.Atan(sineLatitude*Math.Tan(shr*Degrees))/Degrees; Console.WriteLine("{0}\t\t{1}\t\t{2:0.000}",clockHour,shr,dhla)
done
//To keep the console window open, can be omitted with block comment (" (* comment *) ") Console.WriteLine("Press any key to continue...") Console.ReadKey() |> ignore</lang>
- Example output:
Enter latitude: -4.95 Enter longitude: -150.5 Enter legal meridian: -150 Sine of latitude: -0.0862863657979234 Difference of Longitudes (given longitude - meridian): -0.5 Numbers from 6 AM to 6 PM: Hour Sun hour angle Dial hour line angle 6AM -89.5 84.225 5AM -74.5 17.283 4AM -59.5 8.334 3AM -44.5 4.847 2AM -29.5 2.795 1AM -14.5 1.278 0PM 0.5 -0.043 1PM 15.5 -1.371 2PM 30.5 -2.910 3PM 45.5 -5.018 4PM 60.5 -8.671 5PM 75.5 -18.451 6PM 90.5 84.225 Press any key to continue...
Factor
<lang factor>USING: formatting io kernel locals math math.functions math.libm math.parser math.ranges math.trig sequences ; IN: rosetta-code.sundial
- get-num ( str -- x ) write flush readln string>number ;
- get-input ( -- lat lng ref )
"Enter latitude: " "Enter longitude: " "Enter legal meridian: " [ get-num ] tri@ ;
- .diff ( lat lng ref -- )
- [ deg>rad sin ] dip "sine of latitude: %.3f\ndiff longitude: %.3f\n" printf ;
- line-angle ( lat hra-rad -- hla )
[ deg>rad sin ] [ [ sin * ] [ cos ] bi ] bi* fatan2 rad>deg ;
- .angles ( lat lng ref -- )
"Hour, sun hour angle, dial hour line angle from 6am to 6pm" print -6 6 [a,b] [ :> h 15.0 h * :> hra! ref hra lng - + hra! lat hra deg>rad line-angle :> hla h hra hla "HR= %3d; \t HRA=%7.3f; \t HLA= %7.3f\n" printf ] each ;
- sundial-demo ( -- ) get-input nl 3dup .diff nl .angles ;
MAIN: sundial-demo</lang>
- Output:
Enter latitude: -4.95 Enter longitude: -150.5 Enter legal meridian: -150 sine of latitude: -0.086 diff longitude: -0.500 Hour, sun hour angle, dial hour line angle from 6am to 6pm HR= -6; HRA=-89.500; HLA= 84.225 HR= -5; HRA=-74.500; HLA= 17.283 HR= -4; HRA=-59.500; HLA= 8.334 HR= -3; HRA=-44.500; HLA= 4.847 HR= -2; HRA=-29.500; HLA= 2.795 HR= -1; HRA=-14.500; HLA= 1.278 HR= 0; HRA= 0.500; HLA= -0.043 HR= 1; HRA= 15.500; HLA= -1.371 HR= 2; HRA= 30.500; HLA= -2.910 HR= 3; HRA= 45.500; HLA= -5.018 HR= 4; HRA= 60.500; HLA= -8.671 HR= 5; HRA= 75.500; HLA= -18.451 HR= 6; HRA= 90.500; HLA= -95.775
Forth
<lang forth>: faccept ( -- f )
pad 32 accept pad swap >float 0= throw ;
- >radians ( deg -- rad ) 180e f/ pi f* ;
- >degrees ( rad -- deg ) pi f/ 180e f* ;
- sundial
cr ." Enter latitude: " faccept >radians fsin cr ." Enter longitude: " faccept cr ." Enter legal meridian: " faccept f- fnegate ( sin[latitude] -longitude ) cr ." Hour : HourAngle , DialAngle" 7 -6 do cr i 4 .r ." : " fover fover i 15 * s>d d>f f+ fdup f. ." , " >radians fsincos fswap frot f* fswap fatan2 >degrees f. loop fdrop fdrop ;</lang>
Fortran
with -fbackslash option
<lang fortran>program SunDial
real :: lat, slat, lng, ref real :: hra, hla integer :: h
real, parameter :: pi = 3.14159265358979323846
print *, "Enter latitude" read *, lat print *, "Enter longitude" read *, lng print *, "Enter legal meridian" read *, ref
print *
slat = sin(dr(lat)) write(*, '(A,1F6.3)') "sine of latitude: ", slat write(*, '(A,1F6.3)') "diff longitude: ", lng - ref
print *, "Hour, sun hour angle, dial hour line angle from 6am to 6pm"
do h = -6, 6 hra = 15.0*h hra = hra - lng + ref hla = rd( atan( slat * tan( dr(hra) ) ) ) write(*, '(" HR= ",I3,"; \t HRA=",F7.3,"; \t HLA= ", F7.3)'), h, hra, hla end do
contains
function dr(angle) real :: dr real, intent(in) :: angle dr = angle*pi/180.0 end function dr
function rd(angle) real :: rd real, intent(in) :: angle rd = angle*180.0/pi end function rd
end program SunDial</lang>
FreeBASIC
<lang freebasic>' version 04-11-2016 ' compile with: fbc -s console
- Macro deg2rad (x)
(x) * Atn(1) / 45
- EndMacro
- Macro rad2deg (x)
(x) * 45 / Atn(1)
- EndMacro
' ------=< MAIN >=------
Dim As Double latitude, longitude, meridian, hra, hla Dim As ULong h
Input " Enter latitude (degrees): ", latitude Input " Enter longitude (degrees): ", longitude Input "Enter legal meridian (degrees): ", meridian
Print Print " Time Sun hour angle Dial hour line angle"
For h = 6 To 18
hra = h * 15 - longitude + meridian - 180 hla = rad2deg(Atn(Sin(deg2rad(latitude)) * Tan(deg2rad(hra)))) If Abs(hra) > 90 Then hla += 180 * Sgn(hra * latitude) Print Using "##.## ####.### ####.###"; h; hra; hla
Next
' empty keyboard buffer While InKey <> "" : Wend Print : Print "hit any key to end program" Sleep End</lang>
- Output:
Enter latitude (degrees): -4.95 Enter longitude (degrees): -150.5 Enter legal meridian (degrees): -150 Time Sun hour angle Dial hour line angle 6.00 -89.500 84.225 7.00 -74.500 17.283 8.00 -59.500 8.334 9.00 -44.500 4.847 10.00 -29.500 2.795 11.00 -14.500 1.278 12.00 0.500 -0.043 13.00 15.500 -1.371 14.00 30.500 -2.910 15.00 45.500 -5.018 16.00 60.500 -8.671 17.00 75.500 -18.451 18.00 90.500 -95.775
FutureBasic
<lang futurebasic> include "ConsoleWindow"
local fn rad2deg( theta as double ) as double end fn = theta * 180 / pi
local fn deg2rad( theta as double ) as double end fn = theta * pi / 180
local fn SolarHourAngle( latitude as double, longitude as double, meridian as double ) dim as long hour dim as double hra, hla, time dim as Str15 ap
print "Latitude = "; latitude; chr$(13); "Longitude = "; longitude; chr$(13); "Meridian = "; meridian print : print "sine of latitude: "; sin(latitude * pi / 180 ); chr$(13); " diff longitude: "; longitude - meridian print : print "Time", "Sun hour angle", "Dial hour line angle" for hour = 6 to 18 hra = ( 15 * hour ) - longitude + meridian - 180 hla = fn rad2deg( atn( sin( fn deg2rad( latitude ) ) * tan( fn deg2rad( hra ) ))) if abs( hra ) > 90 then hla = hla + 180 * sgn( hra * latitude ) if hour > 12 then time = hour - 12 : ap = " a.m." else time = hour : ap = " p.m." print using "##"; time; ap, using "####.##"; hra, using "####.###"; hla next hour end fn
fn SolarHourAngle( -4.95, -150.5, -150.0 ) </lang>
Output:
Latitude = -4.95 Longitude = -150.5 Meridian = -150 sine of latitude: -0.0862863658 diff longitude: -0.5 Time Sun hour angle Dial hour line angle 6 p.m. -89.50 84.225 7 p.m. -74.50 17.283 8 p.m. -59.50 8.334 9 p.m. -44.50 4.847 10 p.m. -29.50 2.795 11 p.m. -14.50 1.278 12 p.m. 0.50 -0.043 1 a.m. 15.50 -1.371 2 a.m. 30.50 -2.910 3 a.m. 45.50 -5.018 4 a.m. 60.50 -8.671 5 a.m. 75.50 -18.451 6 a.m. 90.50 -95.775
Go
<lang go>package main
import (
"fmt" "math" "os"
)
func getnum(prompt string) (r float64) {
fmt.Print(prompt) if _, err := fmt.Scan(&r); err != nil { fmt.Println(err) os.Exit(-1) } return
}
func main() {
lat := getnum("Enter latitude => ") lng := getnum("Enter longitude => ") ref := getnum("Enter legal meridian => ") slat := math.Sin(lat * math.Pi / 180) diff := lng - ref fmt.Println("\n sine of latitude: ", slat) fmt.Println(" diff longitude: ", diff) fmt.Println("\nHour, sun hour angle, dial hour line angle from 6am to 6pm") for h := -6.; h <= 6; h++ { hra := 15*h - diff s, c := math.Sincos(hra * math.Pi / 180) hla := math.Atan2(slat*s, c) * 180 / math.Pi fmt.Printf("%2.0f %8.3f %8.3f\n", h, hra, hla) }
}</lang>
- Output:
Enter latitude => -4.95 Enter longitude => -150.5 Enter legal meridian => -150 sine of latitude: -0.08628636579792338 diff longitude: -0.5 Hour, sun hour angle, dial hour line angle from 6am to 6pm -6 -89.500 84.225 -5 -74.500 17.283 -4 -59.500 8.334 -3 -44.500 4.847 -2 -29.500 2.795 -1 -14.500 1.278 0 0.500 -0.043 1 15.500 -1.371 2 30.500 -2.910 3 45.500 -5.018 4 60.500 -8.671 5 75.500 -18.451 6 90.500 -95.775
GW-BASIC
<lang qbasic> 10 ' Horizontal sundial calculations 20 PRINT "Enter latitude => "; 30 INPUT LAT 40 PRINT "Enter longitude => "; 50 INPUT LNG 60 PRINT "Enter legal meridian => "; 70 INPUT REF 80 PRINT 90 LET PI = 4 * ATN(1) 100 LET SLAT = SIN(LAT * PI / 180) 110 PRINT " sine of latitude: "; USING "#.##^^^^"; SLAT 120 PRINT " diff longitude: "; USING "####.###"; LNG - REF 130 PRINT 140 PRINT "Hour, sun hour angle, dial hour line angle from 6am to 6pm" 150 FOR H% = -6 TO 6 160 LET HRA = 15 * H% 170 LET HRA = HRA - (LNG - REF): ' correct for longitude difference 180 LET HLA = ATN(SLAT * TAN(HRA * PI / 180)) * 180 / PI 190 PRINT "HR="; USING "+##"; H%; 200 PRINT "; HRA="; USING "+###.###"; HRA; 210 PRINT "; HLA="; USING "+###.###"; HLA 220 NEXT H% 230 END </lang>
- Output:
Enter latitude => ? -4.95 Enter longitude => ? -150.5 Enter legal meridian => ? -150 sine of latitude: -.86E-01 diff longitude: -0.500 Hour, sun hour angle, dial hour line angle from 6am to 6pm HR= -6; HRA= -89.500; HLA= +84.225 HR= -5; HRA= -74.500; HLA= +17.283 HR= -4; HRA= -59.500; HLA= +8.334 HR= -3; HRA= -44.500; HLA= +4.847 HR= -2; HRA= -29.500; HLA= +2.795 HR= -1; HRA= -14.500; HLA= +1.278 HR= +0; HRA= +0.500; HLA= -0.043 HR= +1; HRA= +15.500; HLA= -1.371 HR= +2; HRA= +30.500; HLA= -2.910 HR= +3; HRA= +45.500; HLA= -5.018 HR= +4; HRA= +60.500; HLA= -8.671 HR= +5; HRA= +75.500; HLA= -18.451 HR= +6; HRA= +90.500; HLA= +84.225
Haskell
<lang haskell>roundDec :: Int -> Double -> Double roundDec d = (/ 10.0 ^ d) . fromIntegral . round . (* 10.0 ^ d)
radToDegr = ((180 / pi) *)
degrToRad = ((pi / 180) *)
main = do
let lat = -4.95 long = -150.5 legalMerid = -150 sinOfLat = sin $ degrToRad lat diff = legalMerid - long (putStrLn . unlines) [ "Latitude " ++ show lat , "Longitude " ++ show long , "Legal meridian " ++ show legalMerid , "Sine of latitude " ++ show (roundDec 6 sinOfLat) , "Diff longitude " ++ show (-diff) , "hour sun hour angle dial hour line angle" ] mapM_ (\h -> let sha = diff + 15 * h dhla = radToDegr . atan . (sinOfLat *) . tan $ degrToRad sha in putStrLn $ take 7 (show h ++ repeat ' ') ++ take 16 (show (roundDec 3 sha) ++ repeat ' ') ++ " " ++ show (roundDec 3 dhla)) [-6,-5 .. 6]</lang>
- Output:
*Rosetta.HorSunDial> main Latitude -4.95 Longitude -150.5 Legal meridian -150.0 Sine of latitude -8.6286e-2 Diff longitude -0.5 hour sun hour angle dial hour line angle -6.0 -89.5 84.225 -5.0 -74.5 17.283 -4.0 -59.5 8.334 -3.0 -44.5 4.847 -2.0 -29.5 2.795 -1.0 -14.5 1.278 0.0 0.5 -4.3e-2 1.0 15.5 -1.371 2.0 30.5 -2.91 3.0 45.5 -5.018 4.0 60.5 -8.671 5.0 75.5 -18.451 6.0 90.5 84.225
Icon and Unicon
<lang Icon>procedure main()
PrintSundial(-4.95, -150.5, -150);
end
procedure PrintSundial(lat, lng, mer )
write("latitude: ", lat, "\nlongitude: ", lng, "\nlegal meridian: ", mer) slat := sin(dtor(lat)) write("sine of latitude: ",slat, "\ndiff longitude: ", lng-mer) write("\nHour, sun hour angle, dial hour line angle from 6am to 6pm")
every h := -6 to 6 do { hraRad := dtor(hra := 15 * h - (lng - mer)) hla :=rtod(atan(sin(hraRad)*slat, cos(hraRad))) write("HR=", right(if h <= 0 then 12+h else h,2), if h < 0 then "am" else "pm", " HRA=",hra,", HLA=",hla) }
end</lang>
- Output:
latitude: -4.95 longitude: -150.5 legal meridian: -150 sine of latitude: -0.08628636579792337 diff longitude: -0.5 Hour, sun hour angle, dial hour line angle from 6am to 6pm HR= 6am HRA=-89.5, HLA=84.22483260136025 HR= 7am HRA=-74.5, HLA=17.2829335027853 HR= 8am HRA=-59.5, HLA=8.333711921468083 HR= 9am HRA=-44.5, HLA=4.846708924373172 HR=10am HRA=-29.5, HLA=2.794873809318642 HR=11am HRA=-14.5, HLA=1.278352980919063 HR=12pm HRA=0.5, HLA=-0.04314426995813971 HR= 1pm HRA=15.5, HLA=-1.370787843187052 HR= 2pm HRA=30.5, HLA=-2.909643210076617 HR= 3pm HRA=45.5, HLA=-5.018023174356126 HR= 4pm HRA=60.5, HLA=-8.671396957302381 HR= 5pm HRA=75.5, HLA=-18.45099922256532 HR= 6pm HRA=90.5, HLA=-95.77516739863968
IS-BASIC
<lang IS-BASIC>100 PROGRAM "SunDial.bas" 110 OPTION ANGLE RADIANS 120 TEXT 80 130 LET DR=PI/180:LET RD=180/PI 140 INPUT PROMPT "Enter latitude: ":LAT 150 INPUT PROMPT "Enter longitude: ":LNG 160 INPUT PROMPT "Enter legal meridian: ":REF 170 LET S=SIN(LAT*DR) 180 PRINT :PRINT "Sine of latitude :";S 190 PRINT "Diff longitude: ";LNG-REF 200 PRINT " Hour,",,"sun hour angle, dial hour line angle from 6am to 6 pm" 210 FOR H=6 TO 18 220 LET HRA=15*H-LNG+REF 230 LET HLA=ATN(S*TAN(HRA*DR))*RD 240 PRINT "HR = ";H,"HRA =";HRA,"HLA =";HLA 250 NEXT</lang>
J
<lang j>require 'trig' atan2=: {:@*.@j. NB. arc tangent of y divided by x
horiz=: verb define
'lat lng ref'=. y out=. smoutput@,&": 'Latitude ' out lat 'Longitude ' out lng 'Legal meridian ' out ref 'Sine of latitude ' out slat=. sin rfd lat 'Diff longitude ' out -diff=. ref - lng lbl=.'hour ';'sun hour angle ';'dial hour line angle' r=.((,. (,. (atan2 *&slat)/@+.@r.&.rfd)) diff + 15&*) i:6 smoutput lbl ,: ('3.0';'7.3';'7.3') 8!:1 r
)</lang>
- Example:
<lang j> horiz _4.95 _150.5 _150 Latitude _4.95 Longitude _150.5 Legal meridian _150 Sine of latitude _0.0862864 Diff longitude _0.5 ┌──────┬────────────────┬────────────────────┐ │hour │sun hour angle │dial hour line angle│ ├──────┼────────────────┼────────────────────┤ │ -6 │-89.500 │ 84.225 │ │ -5 │-74.500 │ 17.283 │ │ -4 │-59.500 │ 8.334 │ │ -3 │-44.500 │ 4.847 │ │ -2 │-29.500 │ 2.795 │ │ -1 │-14.500 │ 1.278 │ │ 0 │ 0.500 │ -0.043 │ │ 1 │ 15.500 │ -1.371 │ │ 2 │ 30.500 │ -2.910 │ │ 3 │ 45.500 │ -5.018 │ │ 4 │ 60.500 │ -8.671 │ │ 5 │ 75.500 │-18.451 │ │ 6 │ 90.500 │-95.775 │ └──────┴────────────────┴────────────────────┘</lang>
Java
(Substitutes in atan2 for the hour line angle calculation)
<lang java>import java.util.Scanner;
public class Sundial {
public static void main(String[] args) { double lat, slat, lng, ref; Scanner sc = new Scanner(System.in);
System.out.print("Enter latitude: "); lat = sc.nextDouble(); System.out.print("Enter longitude: "); lng = sc.nextDouble(); System.out.print("Enter legal meridian: "); ref = sc.nextDouble(); System.out.println();
slat = Math.sin(Math.toRadians(lat)); System.out.printf("sine of latitude: %.3f\n", slat); System.out.printf("diff longitude: %.3f\n\n", lng - ref);
System.out.printf("Hour, sun hour angle, dial hour line angle from 6am to 6pm\n");
for (int h = -6; h <= 6; h++) { double hla, hra, hraRad; hra = 15.0 * h; hra = hra - lng + ref; hraRad = Math.toRadians(hra); hla = Math.toDegrees(Math.atan2(Math.sin(hraRad)*Math.sin(Math.toRadians(lat)), Math.cos(hraRad))); System.out.printf("HR= %3d; \t HRA=%7.3f; \t HLA= %7.3f\n", h, hra, hla); } }
}</lang>
- Output:
Enter latitude: -4.95 Enter longitude: -150.5 Enter legal meridian: -150 sine of latitude: -0.086 diff longitude: -0.500 Hour, sun hour angle, dial hour line angle from 6am to 6pm HR= -6; HRA=-89.500; HLA= 84.225 HR= -5; HRA=-74.500; HLA= 17.283 HR= -4; HRA=-59.500; HLA= 8.334 HR= -3; HRA=-44.500; HLA= 4.847 HR= -2; HRA=-29.500; HLA= 2.795 HR= -1; HRA=-14.500; HLA= 1.278 HR= 0; HRA= 0.500; HLA= -0.043 HR= 1; HRA= 15.500; HLA= -1.371 HR= 2; HRA= 30.500; HLA= -2.910 HR= 3; HRA= 45.500; HLA= -5.018 HR= 4; HRA= 60.500; HLA= -8.671 HR= 5; HRA= 75.500; HLA= -18.451 HR= 6; HRA= 90.500; HLA= -95.775
Julia
<lang julia> print("Enter latitude => ") lat = parse(Float64, readline(STDIN)) print("Enter longitude => ") lng = parse(Float64, readline(STDIN)) print("Enter legal meridian => ") ref = parse(Float64, readline(STDIN)) println()
slat = sin(deg2rad(lat)) @printf " sine of latitude: %.3f\n" slat @printf " diff longitude: %.3f\n" (lng - ref)
println("\nHour, sun hour angle, dial hour line angle from 6am to 6pm\n")
for h in -6:6
hra = 15 * h hra -= lng - ref hla = rad2deg(atan(slat * tan(deg2rad(hra)))) @printf "HR = %3d; HRA = %7.3f; HLA = %7.3f\n" h hra hla
end </lang>
- Output:
Enter latitude => -4.95 Enter longitude => -150.5 Enter legal meridian => -150 sine of latitude: -0.086 diff longitude: -0.500 Hour, sun hour angle, dial hour line angle from 6am to 6pm HR = -6; HRA = -89.500; HLA = 84.225 HR = -5; HRA = -74.500; HLA = 17.283 HR = -4; HRA = -59.500; HLA = 8.334 HR = -3; HRA = -44.500; HLA = 4.847 HR = -2; HRA = -29.500; HLA = 2.795 HR = -1; HRA = -14.500; HLA = 1.278 HR = 0; HRA = 0.500; HLA = -0.043 HR = 1; HRA = 15.500; HLA = -1.371 HR = 2; HRA = 30.500; HLA = -2.910 HR = 3; HRA = 45.500; HLA = -5.018 HR = 4; HRA = 60.500; HLA = -8.671 HR = 5; HRA = 75.500; HLA = -18.451 HR = 6; HRA = 90.500; HLA = 84.225
Kotlin
<lang scala>import java.lang.Math.atan2 import java.lang.Math.cos import java.lang.Math.sin import java.lang.Math.toDegrees import java.lang.Math.toRadians
// version 1.1.4
fun main(args: Array<String>) {
println("Please enter the following in degrees:") print(" Latitude : ") val lat = readLine()!!.toDouble() print(" Longitude : ") val lng = readLine()!!.toDouble() print(" Legal Meridian : ") val mer = readLine()!!.toDouble()
val slat = sin(toRadians(lat)) val diff = lng - mer println("\nSine of latitude = ${"%.6f".format(slat)}") println("Longitude - Meridian = ${"%.3f".format(diff)}\n") println("Hour Sun Hour Angle Dial Hour Line Angle") println("----- -------------- --------------------") println(" ° °") for (h in -6..6) { var hr = h + 12 val am = if (hr < 12) "AM" else "PM" if (hr > 12) hr -= 12 val sha = 15.0 * h - diff val dhla = toDegrees(atan2(slat * sin(toRadians(sha)), cos(toRadians(sha)))) println("%2d %s %+7.3f %+7.3f".format(hr, am, sha, dhla)) }
}</lang> Sample input/output:
- Output:
Please enter the following in degrees: Latitude : -4.95 Longitude : -150.5 Legal Meridian : -150 Sine of latitude = -0.086286 Longitude - Meridian = -0.500 Hour Sun Hour Angle Dial Hour Line Angle ----- -------------- -------------------- ° ° 6 AM -89.500 +84.225 7 AM -74.500 +17.283 8 AM -59.500 +8.334 9 AM -44.500 +4.847 10 AM -29.500 +2.795 11 AM -14.500 +1.278 12 PM +0.500 -0.043 1 PM +15.500 -1.371 2 PM +30.500 -2.910 3 PM +45.500 -5.018 4 PM +60.500 -8.671 5 PM +75.500 -18.451 6 PM +90.500 -95.775
Liberty BASIC
Based on Algol & BBC BASIC versions. Note Liberty BASIC works in radians. <lang lb>global pi pi = 3.14159265 input "Enter latitude (degrees) : "; latitude ' -4.95 input "Enter longitude (degrees) : "; longitude ' -150.5 input "Enter legal meridian (degrees): "; meridian ' -150.0 print print "Time Sun hour angle Dial hour line angle" for hour = 6 TO 18
hra = 15 * hour - longitude + meridian - 180 hla = rad2deg(atn(sin(deg2rad(latitude)) * tan(deg2rad(hra)))) if abs(hra) > 90 then hla = hla + 180 * sgn(hra * latitude) print using( "##.##", hour), using("####.### ", hra), using("####.###", hla)
next hour end
function rad2deg(theta)
rad2deg = theta * 180 / pi
end function
function deg2rad(theta)
deg2rad = theta * pi / 180
end function
function sgn(x)
if x > 0 then sgn = 1 else sgn = -1
end function</lang>
- Output:
Enter latitude (degrees) : -4.95 Enter longitude (degrees) : -150.5 Enter legal meridian (degrees): -150.0 Time Sun hour angle Dial hour line angle 6.00 -89.500 84.225 7.00 -74.500 17.283 8.00 -59.500 8.334 9.00 -44.500 4.847 10.00 -29.500 2.795 11.00 -14.500 1.278 12.00 0.500 -0.043 13.00 15.500 -1.371 14.00 30.500 -2.910 15.00 45.500 -5.018 16.00 60.500 -8.671 17.00 75.500 -18.451 18.00 90.500 -95.775
LiveCode
Translation of BASIC versions. <lang LiveCode>on mouseUp
ask "Enter lng,lat,meridian" if it is empty then exit mouseup // -150.5, -4.95, -150.0 put item 1 of it into longitude put item 2 of it into latitude put item 3 of it into meridian repeat with hour = 6 TO 18 put 15 *hour - longitude + meridian - 180 into hra put rad2deg(atan(sin(deg2rad(latitude)) * tan(deg2rad(hra)))) into hla if abs(hra) > 90 then put hla + 180 * sgn(hra *latitude) into hla put hour && hra && hla & cr after sunhours end repeat put sunhours
end mouseUp
function rad2deg theta
return theta * (180 / pi)
end rad2deg
function deg2rad theta
return theta * (pi / 180)
end deg2rad
function sgn x
if x >0 then return 1 else return -1
end sgn</lang>
Logo
<lang logo>type "|Enter latitude: | make "lat readword type "|Enter longitude: | make "long readword type "|Enter legal meridian: | make "long :long - readword
print [Hour : HourAngle , DialAngle] for [hour -6 6] [
make "hra 15 * :hour - :long make "hla arctan product sin :lat quotient sin :hra cos :hra print (sentence "hour :hour ": :hra ", :hla)
]</lang>
Lua
<lang lua>io.write("Enter latitude => ") lat = tonumber(io.read())
io.write("Enter longitude => ") lng = tonumber(io.read())
io.write("Enter legal meridian => ") ref = tonumber(io.read())
print()
slat = math.sin(math.rad(lat))
print(string.format(" sine of latitude: %.3f", slat)) print(string.format(" diff longitude: %.3f", lng-ref)) print() print("Hour, sun hour angle, dial hour line angle from 6am to 6pm")
for h = -6, 6 do hra = 15 * h hra = hra - (lng - ref) hla = math.deg(math.atan(slat * math.tan(math.rad(hra)))) print(string.format("HR=%3d; HRA=%7.3f; HLA=%7.3f", h, hra, hla)) end</lang>
Mathematica / Wolfram Language
<lang Mathematica>lat = Input["latitude", -4.95]; lng = Input["longitude", -150.5]; ref = Input["legal meridian", -150];
slat = Sin[lat Degree]; Table[
hra = 15 h; hra -= lng - ref; hla = N@ArcTan[slat Tan[hra Degree]]/Degree; {h, hra, hla} , {h, -6, 6} ] // Prepend[{"Hour", "Sun hour angle", "Dial hour line angle"}] // Grid</lang>
- Output:
Hour Sun hour angle Dial hour line angle -6 -89.5 84.2248 -5 -74.5 17.2829 -4 -59.5 8.33371 -3 -44.5 4.84671 -2 -29.5 2.79487 -1 -14.5 1.27835 0 0.5 -0.0431443 1 15.5 -1.37079 2 30.5 -2.90964 3 45.5 -5.01802 4 60.5 -8.6714 5 75.5 -18.451 6 90.5 84.2248
Microsoft Small Basic
<lang microsoftsmallbasic> TextWindow.Write("Enter latitude => ") lat = TextWindow.ReadNumber() TextWindow.Write("Enter longitude => ") lng = TextWindow.ReadNumber() TextWindow.Write("Enter legal meridian => ") ref = TextWindow.ReadNumber() sLat = Math.Sin(Math.GetRadians(lat)) TextWindow.WriteLine("") TextWindow.Write(" sine of latitude: ") TextWindow.WriteLine(Math.Round(sLat * 10000) / 10000) TextWindow.Write(" diff longitude: ") TextWindow.WriteLine(lng - ref) TextWindow.WriteLine("") TextWindow.WriteLine("Hour, sun hour angle, dial hour line angle from 6am to 6pm") For hour = -6 To 6
hourAngle = 15 * hour hourAngle = hourAngle - (lng - ref) ' correct for longitude difference hourLineAngle = math.GetDegrees(Math.ArcTan(sLat * Math.Tan(Math.GetRadians(hourAngle)))) TextWindow.Write("HR=") TextWindow.CursorLeft = 3 + (3 - Text.GetLength(hour)) TextWindow.Write(hour) TextWindow.Write("; HRA=") TextWindow.CursorLeft = 12 + (6 - Text.GetLength(hourAngle)) TextWindow.Write(hourAngle) TextWindow.Write("; HLA=") TextWindow.CursorLeft = 24 + (4 - Text.GetLength(Math.Floor(hourLineAngle))) TextWindow.Write(Math.Round(hourLineAngle * 1000) / 1000) TextWindow.WriteLine("")
EndFor </lang>
- Output:
Enter latitude => -4.95 Enter longitude => -150.5 Enter legal meridian => -150 sine of latitude: -0.0863 diff longitude: -0.5 Hour, sun hour angle, dial hour line angle from 6am to 6pm HR= -6; HRA= -89.5; HLA= 84.225 HR= -5; HRA= -74.5; HLA= 17.283 HR= -4; HRA= -59.5; HLA= 8.334 HR= -3; HRA= -44.5; HLA= 4.847 HR= -2; HRA= -29.5; HLA= 2.795 HR= -1; HRA= -14.5; HLA= 1.278 HR= 0; HRA= 0.5; HLA= -0.043 HR= 1; HRA= 15.5; HLA= -1.371 HR= 2; HRA= 30.5; HLA= -2.91 HR= 3; HRA= 45.5; HLA= -5.018 HR= 4; HRA= 60.5; HLA= -8.671 HR= 5; HRA= 75.5; HLA= -18.451 HR= 6; HRA= 90.5; HLA= 84.225
МК-61/52
<lang>МГ П2 -> МГ П1 -> МГ sin П0 6 /-/ П3 ИП3 1 5 * ИП1 ИП2 - - П4 tg ИП0 * arctg ИП4 ИП3 С/П ИП3 1 + П3 7 - x=0 12 Сx С/П</lang>
Input: latitude ^ longitude ^ legal meridian С/П ... С/П ...; switch of the angle measure set to Г.
Example: -4,57 ^ -150,3 ^ -150 С/П.
Output: hour in РX, sun hour angle in РY, dial hour line angle in РZ.
Modula-2
<lang modula2> MODULE SunDial;
FROM STextIO IMPORT
WriteString, WriteLn, SkipLine;
FROM SRealIO IMPORT
ReadReal, WriteFixed, WriteFloat;
FROM SWholeIO IMPORT
WriteInt;
FROM RealMath IMPORT
sin, pi, arctan, tan;
VAR
Lat, Slat, Lng, Ref: REAL; Hour: INTEGER; HourAngle, HourLineAngle: REAL;
BEGIN
WriteString("Enter latitude => "); ReadReal(Lat); SkipLine; WriteString("Enter longitude => "); ReadReal(Lng); SkipLine; WriteString("Enter legal meridian => "); ReadReal(Ref); SkipLine; WriteLn; Slat := sin(Lat * pi / 180.0); WriteString(" sine of latitude: "); WriteFloat(Slat, 2, 8); WriteLn; WriteString(" diff longitude: "); WriteFixed(Lng - Ref, 3, 1); WriteLn; WriteLn; WriteString("Hour, sun hour angle, dial hour line angle from 6am to 6pm"); WriteLn; FOR Hour := -6 TO 6 DO HourAngle := FLOAT(15 * Hour); HourAngle := HourAngle - (Lng - Ref); (* correct for longitude difference *) HourLineAngle := arctan(Slat * tan(HourAngle * pi / 180.0)) * 180.0 / pi; WriteString("HR="); WriteInt(Hour, 3); WriteString("; HRA="); WriteFixed(HourAngle, 3, 8); WriteString("; HLA="); WriteFixed(HourLineAngle, 3, 8); WriteLn; END;
END SunDial. </lang>
- Output:
Enter latitude => -4.95 Enter longitude => -150.5 Enter legal meridian => -150 sine of latitude: -8.6E-02 diff longitude: -0.500 Hour, sun hour angle, dial hour line angle from 6am to 6pm HR= -6; HRA= -89.500; HLA= 84.225 HR= -5; HRA= -74.500; HLA= 17.283 HR= -4; HRA= -59.500; HLA= 8.334 HR= -3; HRA= -44.500; HLA= 4.847 HR= -2; HRA= -29.500; HLA= 2.795 HR= -1; HRA= -14.500; HLA= 1.278 HR= 0; HRA= 0.500; HLA= -0.043 HR= 1; HRA= 15.500; HLA= -1.371 HR= 2; HRA= 30.500; HLA= -2.910 HR= 3; HRA= 45.500; HLA= -5.018 HR= 4; HRA= 60.500; HLA= -8.671 HR= 5; HRA= 75.500; HLA= -18.451 HR= 6; HRA= 90.500; HLA= 84.225
newLISP
<lang newLISP>(define pi 3.141592654) (define (radians degrees) (mul degrees (div pi 180))) (define (degrees radians) (mul radians (div 180 pi)))
(print "Enter latitude => ") (set 'lat (float (read-line)))
(print "Enter longitude => ") (set 'lng (float (read-line)))
(print "Enter legal meridian => ") (set 'rf (float (read-line)))
(println)
(set 'slat (sin (radians lat)))
(println (format " sine of latitude: %.3f" slat)) (println (format " diff longitude: %.3f" (sub lng rf))) (println) (println "Hour, sun hour angle, dial hour line angle from 6am to 6pm")
(for (h -6 6) (set 'hra (sub (mul 15 h) lng rf)) (set 'hla (degrees (atan (mul slat (tan (radians hra)))))) (println (format "HR=%3d; HRA=%7.3f; HLA=%7.3f" h hra hla)) )
(exit)</lang>
Nim
<lang nim>import rdstdin, strutils, math, strformat
let lat = parseFloat readLineFromStdin "Enter latitude => " let lng = parseFloat readLineFromStdin "Enter longitude => " let med = parseFloat readLineFromStdin "Enter legal meridian => " echo ""
let slat = sin lat.degToRad echo &" sine of latitude: {slat:.3f}" echo &" diff longitude: {lng-med:.3f}" echo "" echo "Hour, sun hour angle, dial hour line angle from 6am to 6pm"
for h in -6..6:
let hra = float(15 * h) - lng + med let hla = arctan(slat * tan(hra.degToRad)).radToDeg echo &"HR={h:3d}; HRA={hra:7.3f}; HLA={hla:7.3f}"</lang>
- Output:
Enter latitude => -4.95 Enter longitude => -150.5 Enter legal meridian => -150 sine of latitude: -0.086 diff longitude: -0.500 Hour, sun hour angle, dial hour line angle from 6am to 6pm HR= -6; HRA=-89.500; HLA= 84.225 HR= -5; HRA=-74.500; HLA= 17.283 HR= -4; HRA=-59.500; HLA= 8.334 HR= -3; HRA=-44.500; HLA= 4.847 HR= -2; HRA=-29.500; HLA= 2.795 HR= -1; HRA=-14.500; HLA= 1.278 HR= 0; HRA= 0.500; HLA= -0.043 HR= 1; HRA= 15.500; HLA= -1.371 HR= 2; HRA= 30.500; HLA= -2.910 HR= 3; HRA= 45.500; HLA= -5.018 HR= 4; HRA= 60.500; HLA= -8.671 HR= 5; HRA= 75.500; HLA=-18.451 HR= 6; HRA= 90.500; HLA= 84.225
Objeck
<lang objeck> class Sundial {
function : Main(args : String[]) ~ Nil { "Enter latitude: "->Print(); lat := System.IO.Console->ReadString()->ToFloat(); "Enter longitude: "->Print(); lng := System.IO.Console->ReadString()->ToFloat(); "Enter legal meridian: "->Print(); ref := System.IO.Console->ReadString()->ToFloat(); '\n'->PrintLine(); slat := lat->ToRadians()->Sin(); "sine of latitude: {$slat}"->PrintLine(); value := lng - ref; "diff longitude: {$value}"->PrintLine(); '\n'->PrintLine();
"Hour\t\tsun hour angle\t\tdial hour line angle from 6am to 6pm"->PrintLine(); for (h := -6; h <= 6; h+=1;) { hra := 15.0 * h; hra -= lng - ref; hla := (slat* (hra*2*Float->Pi()/360.0)->Tan())->ArcTan() * 360.0 / (2*Float->Pi()); "HR={$h}\t\tHRA={$hra}\t\tHLA={$hla}"->PrintLine(); }; }
} </lang>
OCaml
<lang ocaml>let () =
let pi = 4. *. atan 1. in print_endline "Enter latitude => "; let lat = read_float () in print_endline "Enter longitude => "; let lng = read_float () in print_endline "Enter legal meridian => "; let ref = read_float () in print_newline (); let slat = sin (lat *. 2. *. pi /. 360.) in Printf.printf " sine of latitude: %.3f\n" slat; Printf.printf " diff longitude: %.3f\n" (lng -. ref); print_newline (); print_endline "Hour, sun hour angle, dial hour line angle from 6am to 6pm"; for h = -6 to 6 do let hra = 15. *. float h in let hra = hra -. (lng -. ref) in let hla = atan (slat *. tan (hra *. 2. *. pi /. 360.)) *. 360. /. (2. *. pi) in Printf.printf "HR= %3d; \t HRA=%7.3f; \t HLA= %7.3f\n" h hra hla; done
</lang>
- Output:
Enter latitude => -4.95 Enter longitude => -150.5 Enter legal meridian => -150. sine of latitude: -0.086 diff longitude: -0.500 Hour, sun hour angle, dial hour line angle from 6am to 6pm HR= -6; HRA=-89.500; HLA= 84.225 HR= -5; HRA=-74.500; HLA= 17.283 HR= -4; HRA=-59.500; HLA= 8.334 HR= -3; HRA=-44.500; HLA= 4.847 HR= -2; HRA=-29.500; HLA= 2.795 HR= -1; HRA=-14.500; HLA= 1.278 HR= 0; HRA= 0.500; HLA= -0.043 HR= 1; HRA= 15.500; HLA= -1.371 HR= 2; HRA= 30.500; HLA= -2.910 HR= 3; HRA= 45.500; HLA= -5.018 HR= 4; HRA= 60.500; HLA= -8.671 HR= 5; HRA= 75.500; HLA= -18.451 HR= 6; HRA= 90.500; HLA= 84.225
Octave
<lang octave>lat = input("Enter latitude: "); lng = input("Enter longitude: "); ref = input("Enter legal meridian: "); slat = sind(lat); printf("sine of latitude: %.3f\n", slat); printf("diff longitude: %.3f\n\n", lng - ref); printf("Hour, sun hour angle, dial hour line angle from 6am to 6pm\n");
hras = [-6:6] .* 15.0 .- lng .+ ref; hlas = atand( tand(hras) .* slat ); printf("HR= %3d; \t HRA=%7.3f; \t HLA= %7.3f\n",
[ [-6:6]; hras; hlas] );</lang>
OoRexx
<lang oorexx>/*REXX pgm shows: hour, sun hour angle, dial hour line angle, 6am ---> 6pm*/ /* Use trigonometric functions provided by rxCalc */ parse arg lat lng mer . /*get the optional arguments from the CL*/
/*None specified? Then use the default of Jules */ /*Verne's Lincoln Island, aka Ernest Legouve Reef.*/
if lat== | lat==',' then lat=-4.95 /*Not specified? Then use the default.*/ if lng== | lng==',' then lng=-150.5 /* " " " " " " */ if mer== | mer==',' then mer=-150 /* " " " " " " */ L=max(length(lat), length(lng), length(mer)) say ' latitude:' right(lat,L) say ' longitude:' right(lng,L) say ' legal meridian:' right(mer,L) sineLat=rxCalcSin(lat,,'D') w1=max(length('hour') ,length('midnight'))+2 w2=max(length('sun hour') ,length('angle'))+2 w3=max(length('dial hour'),length('line angle'))+2 indent=left(,30) /*make the presentation prettier. */ say indent center(' ',w1) center('sun hour',w2) center('dial hour' ,w3) say indent center('hour',w1) center('angle' ,w2) center('line angle',w3) call sep /*add a separator line for the eyeballs*/
do h=-6 to 6 /*Okey dokey then, let's get busy. */
select when abs(h)==12 then hc='midnight' /*above the arctic circle? */ when h<0 then hc=-h 'am' /*convert the hour for human beans. */ when h==0 then hc='noon' /* ... easier to understand now. */ when h>0 then hc=h 'pm' /* ... even more meaningful. */ end /*select*/ hra=15*h-lng+mer hla=rxCalcArctan(sineLat*rxCalctan(hra,,'D'),,'D') say indent center(hc,w1) right(format(hra,,1),w2) right(format(hla,,1),w3) end
call sep Exit sep: say indent copies('-',w1) copies('-',w2) copies('-',w3)
Return
- Requires rxMath Library</lang>
- Output:
Not the same as for REXX anymore as the REXX computer programming example has been updated.
Pascal
<lang pascal>Program SunDial;
Const
pi = 3.14159265358979323846; dr = pi/180.0; rd = 180.0/pi; tab = chr(9);
Var
lat, slat, lng, ref : Real; hla, hra : Real; h : Integer;
function tan(val : Real) : Real; begin
tan := sin(val)/cos(val)
end;
Begin
Write('Enter latitude: '); Read(lat); Write('Enter longitude: '); Read(lng); Write('Enter legal meridian: '); Read(ref); WriteLn; slat := sin(lat * dr); WriteLn('sine of latitude: ', slat); WriteLn('diff longitude: ', lng - ref); WriteLn('Hour, sun hour angle, dial hour line angle from 6am to 6pm'); for h := -6 to 6 do begin hra := 15.0 * h; hra := hra - lng + ref; hla := arctan(slat * tan(hra * dr)) * rd; WriteLn('HR= ', h:3, '; ',
tab, ' HRA= ', hra:7:3, '; ', tab, ' HLA= ', hla:7:3)
end
end.</lang>
Perl
<lang perl>use utf8; binmode STDOUT, ":utf8";
use constant π => 3.14159265;
sub d2r { $_[0] * π / 180 } # degrees to radians sub r2d { $_[0] * 180 / π } # radians to degrees
print 'Enter latitude => '; $latitude = <>; print 'Enter longitude => '; $longitude = <>; print 'Enter legal meridian => '; $meridian = <>;
$lat_sin = sin( d2r($latitude) ); $offset = $meridian - $longitude; print 'Sine of latitude: ' . sprintf "%.4f\n", $lat_sin; print 'Longitude offset: ' . $offset . "\n"; print '=' x 48 . "\n"; print " Hour : Sun hour angle°: Dial hour line angle°\n";
for $hour (-6 .. 6) {
my $sun_deg = $hour * 15 + $offset; my $line_deg = r2d atan2( ( sin(d2r($sun_deg)) * $lat_sin ), cos(d2r($sun_deg)) ); printf "%2d %s %8.3f %8.3f\n", ($hour + 12) % 12 || 12, ($hour < 0 ? 'AM' : 'PM'), $sun_deg, $line_deg;
}</lang>
- Output:
Enter latitude => -4.95 Enter longitude => -150.5 Enter legal meridian => -150 Sine of latitude: -0.0863 Longitude offset: 0.5 ================================================ Hour : Sun hour angle°: Dial hour line angle° 6 AM -89.500 84.225 7 AM -74.500 17.283 8 AM -59.500 8.334 9 AM -44.500 4.847 10 AM -29.500 2.795 11 AM -14.500 1.278 12 PM 0.500 -0.043 1 PM 15.500 -1.371 2 PM 30.500 -2.910 3 PM 45.500 -5.018 4 PM 60.500 -8.671 5 PM 75.500 -18.451 6 PM 90.500 -95.775
Phix
For better behaviour/proper input on pwa/p2js I suppose this should really be a pGUI app.
with javascript_semantics function prompt(string text, atom v) if platform()!=JS then printf(1,"Enter %s (%g):",{text,v}) object answer = gets(0) puts(1, '\n') if string(answer) then v = to_number(trim(answer),v) end if else printf(1,"%s:%g\n",{text,v}) end if return v end function constant deg2rad = PI/180, rad2deg = 180/PI atom lat = prompt("Latitude",-4.95), lng = prompt("Longitude",-150.5), mer = prompt("Legal Meridian",-150), slat = sin(lat*deg2rad) printf(1,""" Sine of latitude: %g Longitude offset: %g Hour Sun hour angle Dial hour line angle -------- -------------- -------------------- """,{slat,lng-mer}) for hour = -6 to 6 do atom ha = hour * 15 - lng + mer, s = sin(ha*deg2rad), c = cos(ha*deg2rad), hla = atan2(slat*s,c)*rad2deg integer hour12 = iff(hour<=0?hour+12:hour) string am = iff(hour<0?"am":"pm") printf(1,"%3d:00%s %12.3f %17.3f\n",{hour12,am,ha,hla}) end for
- Output:
Enter Latitude (-4.95): Enter Longitude (-150.5): Enter Legal Meridian (-150): Sine of latitude: -0.086286 Longitude offset: -0.5 Hour Sun hour angle Dial hour line angle -------- -------------- -------------------- 6:00am -89.500 84.225 7:00am -74.500 17.283 8:00am -59.500 8.334 9:00am -44.500 4.847 10:00am -29.500 2.795 11:00am -14.500 1.278 12:00pm 0.500 -0.043 1:00pm 15.500 -1.371 2:00pm 30.500 -2.910 3:00pm 45.500 -5.018 4:00pm 60.500 -8.671 5:00pm 75.500 -18.451 6:00pm 90.500 -95.775
PicoLisp
<lang PicoLisp>(load "@lib/math.l")
(de prompt (Str . Arg)
(prin Str " => ") (set (car Arg) (in NIL (read))) )
(use (Lat Lng Ref)
(prompt "Enter latitude " Lat) (prompt "Enter longitude " Lng) (prompt "Enter legal meridian" Ref) (prinl) (let Slat (sin (*/ Lat pi 180.0)) (prinl " sine of latitude: " (round Slat)) (prinl " diff longitude: " (round (- Lng Ref))) (prinl) (prinl "Hour, sun hour angle, dial hour line angle from 6am to 6pm") (for H (range -6 6) (let Hra (- (* 15.0 H) (- Lng Ref)) (let Hla (*/ (atan (*/ Slat (tan (*/ Hra pi 180.0)) 1.0)) 180.0 pi) (prinl "HR=" (align 3 H) "; HRA=" (align 8 (round Hra)) "; HLA=" (align 8 (round Hla)) ) ) ) ) ) )</lang>
- Output:
Enter latitude => -4.95 Enter longitude => -150.5 Enter legal meridian => -150. # Don't omit the '.' here sine of latitude: -0.086 diff longitude: -0.500 Hour, sun hour angle, dial hour line angle from 6am to 6pm HR= -6; HRA= -89.500; HLA= 84.225 HR= -5; HRA= -74.500; HLA= 17.283 HR= -4; HRA= -59.500; HLA= 8.334 HR= -3; HRA= -44.500; HLA= 4.847 HR= -2; HRA= -29.500; HLA= 2.795 HR= -1; HRA= -14.500; HLA= 1.278 HR= 0; HRA= 0.500; HLA= -0.043 HR= 1; HRA= 15.500; HLA= -1.371 HR= 2; HRA= 30.500; HLA= -2.910 HR= 3; HRA= 45.500; HLA= -5.018 HR= 4; HRA= 60.500; HLA= -8.671 HR= 5; HRA= 75.500; HLA= -18.451 HR= 6; HRA= 90.500; HLA= 84.225
PowerShell
<lang PowerShell> function Get-Sundial {
[CmdletBinding()] [OutputType([PSCustomObject])] Param ( [Parameter(Mandatory=$true)] [ValidateRange(-90,90)] [double] $Latitude,
[Parameter(Mandatory=$true)] [ValidateRange(-180,180)] [double] $Longitude,
[Parameter(Mandatory=$true)] [ValidateRange(-180,180)] [double] $Meridian )
[double]$sinLat = [Math]::Sin($Latitude*2*[Math]::PI/360)
$object = [PSCustomObject]@{ "Sine of Latitude" = [Math]::Round($sinLat,3) "Longitude Difference" = $Longitude - $Meridian } [int[]]$hours = -6..6
$hoursArray = foreach ($hour in $hours) { [double]$hra = (15 * $hour) - ($Longitude - $Meridian) [double]$hla = [Math]::Atan($sinLat*[Math]::Tan($hra*2*[Math]::PI/360))*360/(2*[Math]::PI) [PSCustomObject]@{ "Hour" = "{0,8}" -f ((Get-Date -Hour ($hour + 12) -Minute 0).ToString("t")) "Sun Hour Angle" = [Math]::Round($hra,3) "Dial Hour Line Angle" = [Math]::Round($hla,3) } }
$object | Add-Member -MemberType NoteProperty -Name Hours -Value $hoursArray -PassThru
}
$sundial = Get-Sundial -Latitude -4.95 -Longitude -150.5 -Meridian -150 $sundial | Select-Object -Property "Sine of Latitude", "Longitude Difference" | Format-List $sundial.Hours | Format-Table -AutoSize </lang>
- Output:
Sine of Latitude : -0.086 Longitude Difference : -0.5 Hour Sun Hour Angle Dial Hour Line Angle ---- -------------- -------------------- 6:00 AM -89.5 84.225 7:00 AM -74.5 17.283 8:00 AM -59.5 8.334 9:00 AM -44.5 4.847 10:00 AM -29.5 2.795 11:00 AM -14.5 1.278 12:00 PM 0.5 -0.043 1:00 PM 15.5 -1.371 2:00 PM 30.5 -2.91 3:00 PM 45.5 -5.018 4:00 PM 60.5 -8.671 5:00 PM 75.5 -18.451 6:00 PM 90.5 84.225
PureBasic
<lang PureBasic>If OpenConsole()
Define.f lat, slat, lng, ref Define.i h Print("Enter latitude => "): lat=ValF(Input()) Print("Enter longitude => "): lng=ValF(Input()) Print("Enter legal meridian => "): ref=ValF(Input()) PrintN("") slat=Sin(lat*2*#PI/360) PrintN(" sine of latitude: "+StrF(slat,3)) PrintN(" diff longitude: "+StrF((lng-ref),3)+#CRLF$) PrintN("Hour, sun hour angle, dial hour line angle from 6am to 6pm") For h=-6 To 6 Define.f hra, hla hra=15*h hra=hra-(lng-ref) hla=ATan(slat*Tan(hra*2*#PI/360))*360/(2*#PI) PrintN("HR="+RSet(Str(h),3)+"; HRA="+RSet(StrF(hra,3),7)+"; HLA="+RSet(StrF(hla,3),7)) Next
EndIf</lang>
- Output:
Enter latitude => -4.95 Enter longitude => -150.5 Enter legal meridian => -150 sine of latitude: -0.086 diff longitude: -0.500 Hour, sun hour angle, dial hour line angle from 6am to 6pm HR= -6; HRA=-89.500; HLA= 84.225 HR= -5; HRA=-74.500; HLA= 17.283 HR= -4; HRA=-59.500; HLA= 8.334 HR= -3; HRA=-44.500; HLA= 4.847 HR= -2; HRA=-29.500; HLA= 2.795 HR= -1; HRA=-14.500; HLA= 1.278 HR= 0; HRA= 0.500; HLA= -0.043 HR= 1; HRA= 15.500; HLA= -1.371 HR= 2; HRA= 30.500; HLA= -2.910 HR= 3; HRA= 45.500; HLA= -5.018 HR= 4; HRA= 60.500; HLA= -8.671 HR= 5; HRA= 75.500; HLA=-18.451 HR= 6; HRA= 90.500; HLA= 84.225
Python
<lang python>from __future__ import print_function import math try: raw_input except: raw_input = input
lat = float(raw_input("Enter latitude => ")) lng = float(raw_input("Enter longitude => ")) ref = float(raw_input("Enter legal meridian => ")) print()
slat = math.sin(math.radians(lat)) print(" sine of latitude: %.3f" % slat) print(" diff longitude: %.3f" % (lng-ref)) print() print("Hour, sun hour angle, dial hour line angle from 6am to 6pm")
for h in range(-6, 7):
hra = 15 * h hra -= lng - ref hla = math.degrees(math.atan(slat * math.tan(math.radians(hra)))) print("HR=%3d; HRA=%7.3f; HLA=%7.3f" % (h, hra, hla))</lang>
- Output:
Enter latitude => -4.95 Enter longitude => -150.5 Enter legal meridian => -150 sine of latitude: -0.086 diff longitude: -0.500 Hour, sun hour angle, dial hour line angle from 6am to 6pm HR= -6; HRA=-89.500; HLA= 84.225 HR= -5; HRA=-74.500; HLA= 17.283 HR= -4; HRA=-59.500; HLA= 8.334 HR= -3; HRA=-44.500; HLA= 4.847 HR= -2; HRA=-29.500; HLA= 2.795 HR= -1; HRA=-14.500; HLA= 1.278 HR= 0; HRA= 0.500; HLA= -0.043 HR= 1; HRA= 15.500; HLA= -1.371 HR= 2; HRA= 30.500; HLA= -2.910 HR= 3; HRA= 45.500; HLA= -5.018 HR= 4; HRA= 60.500; HLA= -8.671 HR= 5; HRA= 75.500; HLA=-18.451 HR= 6; HRA= 90.500; HLA= 84.225
Racket
I must say, I'm a bit astonished by the fact that no one is bothered by the atan problem (HLA=84.225) that appears in the ALGOL 68 solution and all of the ones derived from it. Composing tan & atan produces the identity only in the range [-90,90], and you have to correct for angles outside of this.
Also, I apologize for the length; I added quite a bit of commenting, and I peeled things out into functions so I could test them. Hopefully, the result--though longer--is also more readable.
<lang Racket>#lang racket
- print the table for a given latitude and longitude-offset,
- given in degrees
(define (print-table lat long-offset)
;; print the table header (display (~a " sine of latitude: " (~r (sin (deg->rad lat)) #:precision '(= 3)) "\n" " diff longitude: " (~r long-offset #:precision '(= 3)) "\n\nHour, sun hour angle, dial hour line angle " "from 6am to 6pm\n")) ;; print the table (for ([h (in-range -6 7)]) (define hra (- (* 15 h) long-offset)) (define hla (to-hla lat hra)) (display (~a "HR="(pad-to 3 (~a h))"; " "HRA="(pad-to 7 (~r hra #:precision '(= 3)))"; " "HLA="(pad-to 7 (~r hla #:precision '(= 3)))"\n"))))
- compute the angle on the gnomon corresponding to a
- given angle of the sun (angles given and returned in degrees)
(define (to-hla lat ang)
(define lat-sign (cond [(< lat 0) -1] [else 1])) ;; move to the right quadrant for ;; angles outside [-90,90] (define correction (* (cond [(< ang -90) -180] [(> ang 90) 180] [else 0]) lat-sign)) (+ (rad->deg (atan (* (sin (deg->rad lat)) (tan (deg->rad ang))))) correction))
- write the prompt, return the entered number
(define (prompt->num p)
(printf "~a" p) (string->number (read-line)))
- translate degrees to radians
(define (deg->rad d) (* 2 pi (/ d 360)))
- translate radians to degrees
(define (rad->deg r) (* 360 (/ r (* 2 pi))))
- add spaces to reach given length
(define (pad-to cols str)
(define spaces-needed (max 0 (- cols (string-length str)))) (string-append (list->string (for/list ([i spaces-needed]) #\space)) str))
- INPUT PARAMETERS, PRINT TABLE
(define lat (prompt->num "Enter latitude => ")) (define lng (prompt->num "Enter longitude => ")) (define ref (prompt->num "Enter legal meridian => "))
(print-table lat (- lng ref))
- test cases for angle conversion
(require rackunit) (check < (to-hla 30 89) 90) (check-= (to-hla 30 90) 90 1e-5) (check > (to-hla 30 91) 90) (check > (to-hla 30 -89) -90) (check-= (to-hla 30 90) 90 1e-5) (check < (to-hla 30 -91) -90) (check < (to-hla -30 -89) 90) (check-= (to-hla -30 -90) 90 1e-5) (check > (to-hla -30 -91) 90) (check > (to-hla -30 89) -90) (check-= (to-hla -30 90) -90 1e-5) (check < (to-hla -30 91) -90) </lang>
- Output:
Welcome to DrRacket, version 5.3.3.5--2013-02-20(5eddac74/d) [3m]. Language: racket; memory limit: 512 MB. Enter latitude => -4.95 Enter longitude => -150.5 Enter legal meridian => -150 sine of latitude: -0.086 diff longitude: -0.500 Hour, sun hour angle, dial hour line angle from 6am to 6pm HR= -6; HRA=-89.500; HLA= 84.225 HR= -5; HRA=-74.500; HLA= 17.283 HR= -4; HRA=-59.500; HLA= 8.334 HR= -3; HRA=-44.500; HLA= 4.847 HR= -2; HRA=-29.500; HLA= 2.795 HR= -1; HRA=-14.500; HLA= 1.278 HR= 0; HRA= 0.500; HLA= -0.043 HR= 1; HRA= 15.500; HLA= -1.371 HR= 2; HRA= 30.500; HLA= -2.910 HR= 3; HRA= 45.500; HLA= -5.018 HR= 4; HRA= 60.500; HLA= -8.671 HR= 5; HRA= 75.500; HLA=-18.451 HR= 6; HRA= 90.500; HLA=-95.775 >
Raku
(formerly Perl 6) <lang perl6>sub postfix:<°> ($a) { $a * pi / 180 } # degrees to radians sub postfix:<®> ($a) { $a * 180 / pi } # radians to degrees
my $latitude = prompt 'Enter latitude => '; my $longitude = prompt 'Enter longitude => '; my $meridian = prompt 'Enter legal meridian => ';
my $lat_sin = sin( $latitude° ); say 'Sine of latitude: ', $lat_sin.fmt("%.4f"); say 'Longitude offset: ', my $offset = $meridian - $longitude; say '=' x 48; say ' Hour : Sun hour angle° : Dial hour line angle°';
for -6 .. 6 -> $hour {
my $sun_deg = $hour * 15 + $offset; my $line_deg = atan2( ( sin($sun_deg°) * $lat_sin ), cos($sun_deg°) )®; printf "%2d %s %7.3f %7.3f\n", ($hour + 12) % 12 || 12, ($hour < 0 ?? 'AM' !! 'PM'), $sun_deg, $line_deg;
}</lang>
- Example output:
Enter latitude => -4.95 Enter longitude => -150.5 Enter legal meridian => -150 Sine of latitude: -0.0863 Longitude offset: 0.5 ================================================ Hour : Sun hour angle° : Dial hour line angle° 6 AM -89.500 84.225 7 AM -74.500 17.283 8 AM -59.500 8.334 9 AM -44.500 4.847 10 AM -29.500 2.795 11 AM -14.500 1.278 12 PM 0.500 -0.043 1 PM 15.500 -1.371 2 PM 30.500 -2.910 3 PM 45.500 -5.018 4 PM 60.500 -8.671 5 PM 75.500 -18.451 6 PM 90.500 -95.775
REXX
The REXX language doesn't have the usual trigonometric functions, nor for that matter, a sqrt (square root) function,
so these as well as pi were added to this program.
The legal meridian is calculated instead of relying on a specified amount.
The time range was extended (to include quarter─hour times), and to show that the dial hour line angle just doesn't
change its sign when it exceeds ± 90º.
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. */ numeric digits length( pi() ) - length(.) /*in case sundial is in polar regions. */ parse arg lat lng . /*obtain optional arguments from the CL*/
/* ┌───────────◄ None specified? Then use the default*/ /* │ of Jules Verne's Lincoln Island, */
$= left(, 30) /* ↓ aka Ernest Legouve Reef. */ if lat== | lat=="," then lat= -4.95 /*Not specified? Then use the default.*/ if lng== | lng=="," then lng= -150.5 /* " " " " " " */ mer= format(lng/15, , 0) * 15 /*calculate legal meridian longitude. */ sineLat= sin( d2r(lat) ) /*calculate sine of (radian) latitude. */ w1= max( length('hour' ), length("midnight" )) + 2 /*compute the max hour width*/ w2= max( length('sun hour' ), length("angle" )) + 2 /* " " " angle " */ w3= max( length('dial hour'), length("line angle")) + 2 /* " " " lineº " */ L= max( length(lat), length(lng), length(mer) ) /*find the maximum length of 3 numbers.*/
say ' latitude:' right(lat, L) /*display the latitude to the terminal*/ say ' longitude:' right(lng, L) /* " " longitude " " " */ say ' legal meridian:' right(mer, L) /* " legal meridian " " " */ say $ center(' ', w1) center("sun hour", w2) center('dial hour' , w3) say $ center('hour', w1) center(" angle" , w2) center('line angle', w3)
call sep /*to help a one─eyed pirate's eyeball. */
do h=5 to 19 by .25 /*Okey dokey then, now let's show stuff*/ hra= 15 * h - lng + mer - 180 /*calculate sun hour angle (in degrees)*/ hla= r2d( Atan(sineLat * tan(d2r(hra)))) /*this is the heavy lifting calculation*/ if abs(hra)>90 then hla= hla + 180 * sign(hra*lat) /*adjust for negative angle*/ call civil /*convert the time─of─day to civil time*/ say $ center(hc, w1) right(format(hra,,1), w2-2)@ right(format(hla,,1), w3-5) end /*h*/
call sep /*to help a one─eyed pirate's eyeball. */ exit 0 /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ pi: pi= 3.1415926535897932384626433832795028841971693993751058209749445923078; return pi d2d: return arg(1) // 360 /*normalize degrees ──► a unit circle. */ d2r: return r2r( arg(1) * pi() / 180) /*convert degrees ──► radians. */ r2d: return d2d( (arg(1) * 180 / pi() ) ) /*convert radians ──► degrees. */ r2r: return arg(1) //(pi() * 2) /*normalize radians ──► a unit circle. */ sep: say $ copies('═', w1) copies("═", w2) copies('═', w3); @= left(,3); return 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 AsinErr: call tellErr 'Asin(x), X must be in the range of -1 ──► +1, X=' x AcosErr: call tellErr 'Acos(x), X must be in the range of -1 ──► +1, 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) Atan: procedure; parse arg x; if abs(x)=1 then return pi()*x/4; return Asin(x/sqrt(1+x*x)) /*──────────────────────────────────────────────────────────────────────────────────────*/ Asin: procedure; parse arg x; if x<-1 | x>1 then call AsinErr; s= x*x
if abs(x)>=sqrt(2)*.5 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
/*──────────────────────────────────────────────────────────────────────────────────────*/ 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)
/*──────────────────────────────────────────────────────────────────────────────────────*/ cos: procedure; parse arg x; x= r2r(x); a= abs(x); hpi= pi * .5
numeric fuzz min(6, digits() - 3); if a=pi then return -1 if a=hpi | a=hpi*3 then return 0; if a=pi/3 then return .5 if a=pi * 2 / 3 then return '-.5'; return .sinCos(1, 1, '-1')
/*──────────────────────────────────────────────────────────────────────────────────────*/ .sinCos: parse arg z,!,i; x= x*x; p= z
do #=2 by 2; != -!*x/(#*(#+i)); z= z+!; if z=p then leave; p= z; end; return z
/*──────────────────────────────────────────────────────────────────────────────────────*/ civil: select /* [↓] Maybe below Antarctic circle, */
when h== 0 then hc= 'midnight' /* or above Arctic " */ when h <12 then hc= h 'am' /*convert da hour for human beans (sic)*/ when h==12 then hc= 'noon' /* ··· easier to understand now. */ when h >0 then hc= h 'pm' /* ··· even more meaningful. */ end /*select*/ parse var hc hh ampm .; if \datatype(hh, 'N') then return /*not numeric? */ hh= hh / 1; if hh>12 then hh= hh - 12 /*civil time ? */ if pos(., hh)==0 then do; hc= right(hh, 2)' ' ampm; return; end /*exact hour ? */ parse var hh hr '.' -0 mn; if hr==0 then hr= 12 /*get MN; noon?*/ mn= mn * 60 / 1; hc= right(hr, 2)":"right(mn, 2, 0) ampm; return /*reformat time*/
/*──────────────────────────────────────────────────────────────────────────────────────*/ sqrt: procedure; parse arg x; if x=0 then return 0; d=digits(); numeric digits; h=d+6
m.=9; numeric form; parse value format(x,2,1,,0) 'E0' with g 'E' _ .; g=g*.5'e'_ % 2 do j=0 while h>9; m.j= h; h= h % 2 + 1; end /*j*/ do k=j+5 to 0 by -1; numeric digits m.k; g= (g+x/g) *.5; end /*k*/; return g</lang>
- output when using the default inputs:
latitude: -4.95 longitude: -150.5 legal meridian: -150 sun hour dial hour hour angle line angle ══════════ ══════════ ════════════ 5 am -104.5 161.5 5:15 am -100.8 155.6 5:30 am -97.0 144.9 5:45 am -93.3 123.3 6 am -89.5 84.2 6:15 am -85.8 49.3 6:30 am -82.0 31.5 6:45 am -78.3 22.5 7 am -74.5 17.3 7:15 am -70.8 13.9 7:30 am -67.0 11.5 7:45 am -63.3 9.7 8 am -59.5 8.3 8:15 am -55.8 7.2 8:30 am -52.0 6.3 8:45 am -48.3 5.5 9 am -44.5 4.8 9:15 am -40.8 4.3 9:30 am -37.0 3.7 9:45 am -33.3 3.2 10 am -29.5 2.8 10:15 am -25.8 2.4 10:30 am -22.0 2.0 10:45 am -18.3 1.6 11 am -14.5 1.3 11:15 am -10.8 0.9 11:30 am -7.0 0.6 11:45 am -3.3 0.3 12 pm 0.5 0.0 12:15 pm 4.3 -0.4 12:30 pm 8.0 -0.7 12:45 pm 11.8 -1.0 1 pm 15.5 -1.4 1:15 pm 19.3 -1.7 1:30 pm 23.0 -2.1 1:45 pm 26.8 -2.5 2 pm 30.5 -2.9 2:15 pm 34.3 -3.4 2:30 pm 38.0 -3.9 2:45 pm 41.8 -4.4 3 pm 45.5 -5.0 3:15 pm 49.3 -5.7 3:30 pm 53.0 -6.5 3:45 pm 56.8 -7.5 4 pm 60.5 -8.7 4:15 pm 64.3 -10.1 4:30 pm 68.0 -12.1 4:45 pm 71.8 -14.7 5 pm 75.5 -18.5 5:15 pm 79.3 -24.4 5:30 pm 83.0 -35.1 5:45 pm 86.8 -56.7 6 pm 90.5 -95.8 6:15 pm 94.3 -130.7 6:30 pm 98.0 -148.5 6:45 pm 101.8 -157.5 7 pm 105.5 -162.7 ══════════ ══════════ ════════════
Ring
<lang ring>
- Project : Horizontal sundial calculations
load "stdlib.ring" pi = 22/7 decimals(3)
latitude = -4.95 longitude = -150.5 meridian = -150.0
see "enter latitude (degrees): " + latitude + nl see "enter longitude (degrees): " + longitude + nl see "enter legal meridian (degrees): " + meridian + nl
see "time " + " sun hour angle" + " dial hour line angle" + nl
for hour = 6 to 18
hra = 15*hour - longitude + meridian - 180 hla = 180/pi*(atan(sin(pi/180*latitude) * tan(pi/180*hra))) if fabs(hra) > 90 hla = hla + 180 * sign(hra * latitude) ok see "" + hour + " " + hra + " " + hla + nl
next </lang> Output:
enter latitude (degrees): -4.950 enter longitude (degrees): -150.500 enter legal meridian (degrees): -150 time sun hour angle dial hour line angle 6 -89.500 84.607 7 -74.500 17.316 8 -59.500 8.342 9 -44.500 4.850 10 -29.500 2.796 11 -14.500 1.279 12 0.500 -0.043 13 15.500 -1.371 14 30.500 -2.911 15 45.500 -5.021 16 60.500 -8.680 17 75.500 -18.488 18 90.500 -96.224
Ruby
<lang ruby>include Math DtoR = PI/180
print 'Enter latitude: ' lat = Float( gets ) print 'Enter longitude: ' lng = Float( gets ) print 'Enter legal meridian: ' ref = Float( gets ) puts
slat = sin( lat * DtoR )
puts " sine of latitude: %.3f"% slat puts " diff longitude: %.3f"% (lng-ref) puts puts 'Hour, sun hour angle, dial hour line angle from 6am to 6pm' -6.upto(6) do |h|
hra = 15 * h hra -= lng - ref hla = atan( slat * tan( hra * DtoR ))/ DtoR puts "HR =%3d; HRA =%7.3f; HLA =%7.3f" % [h, hra, hla]
end</lang>
- Output:
Enter latitude: -4.95 Enter longitude: -150.5 Enter legal meridian: -150 sine of latitude: -0.086 diff longitude: -0.500 Hour, sun hour angle, dial hour line angle from 6am to 6pm HR = -6; HRA =-89.500; HLA = 84.225 HR = -5; HRA =-74.500; HLA = 17.283 HR = -4; HRA =-59.500; HLA = 8.334 HR = -3; HRA =-44.500; HLA = 4.847 HR = -2; HRA =-29.500; HLA = 2.795 HR = -1; HRA =-14.500; HLA = 1.278 HR = 0; HRA = 0.500; HLA = -0.043 HR = 1; HRA = 15.500; HLA = -1.371 HR = 2; HRA = 30.500; HLA = -2.910 HR = 3; HRA = 45.500; HLA = -5.018 HR = 4; HRA = 60.500; HLA = -8.671 HR = 5; HRA = 75.500; HLA =-18.451 HR = 6; HRA = 90.500; HLA = 84.225
Run BASIC
<lang runbasic>global pi pi = 22 / 7
print "Enter latitude (degrees) : "; :input latitude ' -4.95 print "Enter longitude (degrees) : "; :input longitude ' -150.5 print "Enter legal meridian (degrees): "; :input meridian ' -150.0
print print "Time Sun hour angle Dial hour line angle"
for hour = 6 TO 18
hra = (15 * hour) - longitude + meridian -180 hla =rad2deg( atn( sin( deg2rad( latitude)) *tan( deg2rad( hra)))) if abs( hra) >90 then hla =hla +180 *sgn( hra *latitude) print using( "##", hour);" ";using("####.##", hra);" ";using("####.###", hla)
next hour
function rad2deg( theta)
rad2deg =theta *180 /pi
end function
function deg2rad( theta)
deg2rad =theta *pi /180
end function
function sgn( x)
if x >0 then sgn =1 else sgn =-1
end function end</lang>
- Output:
Enter latitude: -4.95 Enter longitude: -150.5 Enter legal meridian: -150 Time Sun hour angle Dial hour line angle 6 -89.50 84.606 7 -74.50 17.316 8 -59.50 8.342 9 -44.50 4.850 10 -29.50 2.796 11 -14.50 1.279 12 0.50 -0.043 13 15.50 -1.371 14 30.50 -2.911 15 45.50 -5.021 16 60.50 -8.680 17 75.50 -18.488 18 90.50 -96.224
Rust
<lang rust> use std::io; struct SundialCalculation {
hour_angle: f64, hour_line_angle: f64,
}
fn get_input(prompt: &str) -> Result<f64, Box<dyn std::error::Error>> {
println!("{}", prompt); let mut input = String::new(); let stdin = io::stdin(); stdin.read_line(&mut input)?; Ok(input.trim().parse::<f64>()?)
}
fn calculate_sundial(hour: i8, lat: f64, lng: f64, meridian: f64) -> SundialCalculation {
let diff = lng - meridian; let hour_angle = f64::from(hour) * 15. - diff; let hour_line_angle = (hour_angle.to_radians().tan() * lat.to_radians().sin()) .atan() .to_degrees();
SundialCalculation { hour_angle, hour_line_angle, }
} fn main() -> Result<(), Box<dyn std::error::Error>> {
let lat = get_input("Enter latitude => ")?; let lng = get_input("Enter longitude => ")?; let meridian = get_input("Enter legal meridian => ")?; let diff = lng - meridian;
let sine_lat = lat.to_radians().sin(); println!("Sine of latitude: {:.5}", sine_lat); println!("Diff longitude: {}", diff);
println!(" Hrs Angle Hour Line Angle"); (-6..=6).for_each(|hour| { let sd = calculate_sundial(hour, lat, lng, meridian); println!( "{:>3}{} {:>5} {:>+15.5}", if hour == 0 { 12 } else { (hour + 12) % 12 }, if hour <= 6 { "pm" } else { "am" }, sd.hour_angle, sd.hour_line_angle ); }); Ok(())
}
</lang>
- Output:
Enter latitude => -4.95 Enter longitude => -150.5 Enter legal meridian => -150 Sine of latitude: -0.08629 Diff longitude: -0.5 Hrs Angle Hour Line Angle 6pm -89.5 +84.22483 7pm -74.5 +17.28293 8pm -59.5 +8.33371 9pm -44.5 +4.84671 10pm -29.5 +2.79487 11pm -14.5 +1.27835 12pm 0.5 -0.04314 1pm 15.5 -1.37079 2pm 30.5 -2.90964 3pm 45.5 -5.01802 4pm 60.5 -8.67140 5pm 75.5 -18.45100 6pm 90.5 +84.22483
Sather
<lang sather>class MAIN is
getvalue(s:STR):FLT is #OUT + s + ": "; return #FLT(#IN.get_line.str); end;
dr(a:FLT):FLT is return a * FLT::pi / 180.0; end;
rd(a:FLT):FLT is return a * 180.0 / FLT::pi; end;
main is lat ::= getvalue("Enter latitude"); lng ::= getvalue("Enter longitude"); ref ::= getvalue("Enter legal meridian"); #OUT + "\n"; slat ::= dr(lat).sin; #OUT + "sine of latitude: " + #FMT("%.3f\n", slat); #OUT + "diff longitude: " + #FMT("%.3f\n\n", lng - ref); #OUT + "Hour, sun hour angle, dial hour line angle from 6am to 6pm\n"; loop h ::= (-6).upto!(6); hra ::= 15.0 * h.flt; hra := hra - lng + ref; hla ::= rd((dr(hra).tan * slat).atan); #OUT + #FMT("HR = %3d; \t HRA=%7.3f; \t HLA= %7.3f\n", h, hra, hla); end; end;
end;</lang>
Scala
<lang Scala>import java.util.Scanner
import scala.math.{atan2, cos, sin, toDegrees, toRadians}
object Sundial extends App {
var lat, slat,lng, ref = .0 val sc = new Scanner(System.in) print("Enter latitude: ") lat = sc.nextDouble print("Enter longitude: ") lng = sc.nextDouble print("Enter legal meridian: ") ref = sc.nextDouble println() slat = Math.sin(Math.toRadians(lat)) println(f"sine of latitude: $slat%.3f") println(f"diff longitude: ${lng - ref}%.3f\n") println("Hour, sun hour angle, dial hour line angle from 06h00 to 18h00")
for (h <- -6 to 6) { val hra = 15.0 * h - lng + ref val hraRad = toRadians(hra) val hla = toDegrees(atan2(Math.sin(hraRad) * sin(Math.toRadians(lat)), cos(hraRad))) println(f"HR= $h%3d;\tHRA=$hra%7.3f;\tHLA= $hla%7.3f") }
}</lang>
Seed7
<lang seed7>$ include "seed7_05.s7i";
include "float.s7i"; include "math.s7i";
const float: radianToDegrees is 57.295779513082320876798154814114; const float: degreesToRadian is 0.017453292519943295769236907684883;
const proc: main is func
local var float: lat is 0.0; var float: slat is 0.0; var float: lng is 0.0; var float: meridian is 0.0; var float: hla is 0.0; var float: hra is 0.0; var integer: h is 0; begin write("Enter latitude: "); readln(lat); write("Enter longitude: "); readln(lng); write("Enter legal meridian: "); readln(meridian); writeln; slat := sin(degreesToRadian * lat); writeln("sine of latitude: " <& slat digits 3); writeln("diff longitude: " <& lng - meridian digits 3); writeln; writeln("Hour, sun hour angle, dial hour line angle from 6am to 6pm"); for h range -6 to 6 do hra := 15.0 * flt(h); hra := hra - lng + meridian; hla := radianToDegrees * atan(slat * tan(degreesToRadian * hra)); writeln("HR= " <& h lpad 2 <& "; HRA= " <& hra digits 3 lpad 7 <& "; HLA= " <& hla digits 3 lpad 7); end for; end func;</lang>
- Output:
Enter latitude: -4.95 Enter longitude: -150.5 Enter legal meridian: -150 sine of latitude: -0.086 diff longitude: -0.500 Hour, sun hour angle, dial hour line angle from 6am to 6pm HR= -6; HRA= -89.500; HLA= 84.225 HR= -5; HRA= -74.500; HLA= 17.283 HR= -4; HRA= -59.500; HLA= 8.334 HR= -3; HRA= -44.500; HLA= 4.847 HR= -2; HRA= -29.500; HLA= 2.795 HR= -1; HRA= -14.500; HLA= 1.278 HR= 0; HRA= 0.500; HLA= -0.043 HR= 1; HRA= 15.500; HLA= -1.371 HR= 2; HRA= 30.500; HLA= -2.910 HR= 3; HRA= 45.500; HLA= -5.018 HR= 4; HRA= 60.500; HLA= -8.671 HR= 5; HRA= 75.500; HLA= -18.451 HR= 6; HRA= 90.500; HLA= 84.225
Sidef
<lang ruby>var latitude = read('Enter latitude => ', Number) var longitude = read('Enter longitude => ', Number) var meridian = read('Enter legal meridian => ', Number) var lat_sin = latitude.deg2rad.sin var offset = (meridian - longitude) say('Sine of latitude: ', "%.4f" % lat_sin) say('Longitude offset: ', offset) say('=' * 48) say(' Hour : Sun hour angle° : Dial hour line angle°') for hour (-6 .. 6) {
var sun_deg = (15*hour + offset) var line_deg = rad2deg( atan2( sin(deg2rad(sun_deg)) * lat_sin, cos(deg2rad(sun_deg)) ) ) printf("%2d %s %7.3f %7.3f\n", (hour + 12) % 12 || 12, (hour < 0 ? 'AM' : 'PM'), sun_deg, line_deg)
}</lang>
- Output:
Enter latitude => -4.95 Enter longitude => -150.5 Enter legal meridian => -150 Sine of latitude: -0.0863 Longitude offset: 0.5 ================================================ Hour : Sun hour angle° : Dial hour line angle° 6 AM -89.500 84.225 7 AM -74.500 17.283 8 AM -59.500 8.334 9 AM -44.500 4.847 10 AM -29.500 2.795 11 AM -14.500 1.278 12 PM 0.500 -0.043 1 PM 15.500 -1.371 2 PM 30.500 -2.910 3 PM 45.500 -5.018 4 PM 60.500 -8.671 5 PM 75.500 -18.451 6 PM 90.500 -95.775
Smalltalk
<lang smalltalk>|lat slat lng ref hra hla pi| pi := 1 arcTan * 4. 'Enter latitude: ' display. lat := stdin nextLine asNumber. 'Enter longitude: ' display. lng := stdin nextLine asNumber. 'Enter legal meridian: ' display. ref := stdin nextLine asNumber. slat := lat degreesToRadians sin. ('sine of latitude: %1' % { slat }) displayNl. ('diff longitude: %1' % { lng - ref }) displayNl.
'Hour, sun hour angle, dial hour line angle from 6am to 6pm' displayNl.
-6 to: 6 do: [ :h |
hra := 15.0 * h. hra := hra - lng + ref. hla := (hra degreesToRadians tan * slat) arcTan radiansToDegrees. ('HR= %1; %4 HRA=%2; %4 HLA= %3' % { h. hra. hla. $<9> }) displayNl.
]</lang>
Tcl
<lang tcl>set PI 3.1415927 fconfigure stdout -buffering none puts -nonewline "Enter latitude => "; gets stdin lat puts -nonewline "Enter longitude => "; gets stdin lng puts -nonewline "Enter legal meridian => "; gets stdin ref puts ""
set slat [expr {sin($lat*$PI/180)}] puts [format " sine of latitude: %8g" $slat] puts [format " diff longitude: %3.3f" [expr {$lng - $ref}]] puts "" puts "Hour, sun hour angle, dial hour line angle from 6am to 6pm"
for {set h -6} {$h<=6} {incr h} {
set hra [expr {15.0 * $h}]; # hour angle is 15 times the hour # set hra [expr {$hra-$lng+$ref}]; # but correct for longitude difference # set hla [expr {atan($slat * tan($hra*$PI/180)) * 180/$PI}] puts [format "HR=%+3d; HRA=%+8.3f; HLA=%+8.3f" $h $hra $hla]
}</lang>
- Sample output:
Enter latitude => -4.95 Enter longitude => -150.5 Enter legal meridian => -150 sine of latitude: -0.0862864 diff longitude: -0.500 Hour, sun hour angle, dial hour line angle from 6am to 6pm HR= -6; HRA= -89.500; HLA= +84.225 HR= -5; HRA= -74.500; HLA= +17.283 HR= -4; HRA= -59.500; HLA= +8.334 HR= -3; HRA= -44.500; HLA= +4.847 HR= -2; HRA= -29.500; HLA= +2.795 HR= -1; HRA= -14.500; HLA= +1.278 HR= +0; HRA= +0.500; HLA= -0.043 HR= +1; HRA= +15.500; HLA= -1.371 HR= +2; HRA= +30.500; HLA= -2.910 HR= +3; HRA= +45.500; HLA= -5.018 HR= +4; HRA= +60.500; HLA= -8.671 HR= +5; HRA= +75.500; HLA= -18.451 HR= +6; HRA= +90.500; HLA= +84.225
Wren
<lang ecmascript>import "io" for Stdin, Stdout import "/fmt" for Fmt
var getNum = Fn.new { |prompt|
while (true) { System.write(prompt) Stdout.flush() var input = Stdin.readLine() var n = Num.fromString(input) if (n) return n System.print("Invalid number, try again.") }
}
var lat = getNum.call("Enter latitude : ") var lng = getNum.call("Enter longitude : ") var ref = getNum.call("Enter legal meridian : ") var slat = (lat * Num.pi / 180).sin var diff = lng - ref System.print("\n sine of latitude : %(slat)") System.print(" diff longitude : %(diff)") System.print("\nHour, sun hour angle, dial hour line angle from 6am to 6pm") for (h in -6..6) {
var hra = 15*h - diff var s = (hra * Num.pi /180).sin var c = (hra * Num.pi /180).cos var hla = (slat*s).atan(c) * 180 / Num.pi Fmt.print("$2.0f $8.3f $8.3f", h, hra, hla)
}</lang>
- Output:
Enter latitude : -4.95 Enter longitude : -150.5 Enter legal meridian : -150 sine of latitude : -0.086286365797923 diff longitude : -0.5 Hour, sun hour angle, dial hour line angle from 6am to 6pm -6 -89.500 84.225 -5 -74.500 17.283 -4 -59.500 8.334 -3 -44.500 4.847 -2 -29.500 2.795 -1 -14.500 1.278 0 0.500 -0.043 1 15.500 -1.371 2 30.500 -2.910 3 45.500 -5.018 4 60.500 -8.671 5 75.500 -18.451 6 90.500 -95.775
x86 Assembly
It must be linked with the C standard library and startup code. <lang asm> global main extern printf, scanf
section .text
getvalue: push edx push eax call printf add esp, 4 push in_ft call scanf add esp, 8 ret
st0dr: fld qword [drfact] fmul ret
main:
lea eax, [lat_t]
lea edx, [lat]
call getvalue
lea eax, [lng_t]
lea edx, [lng]
call getvalue
lea eax, [ref_t]
lea edx, [ref]
call getvalue
push newline call printf add esp, 4
fld qword [lat] call st0dr fsin fst qword [slat]
sub esp, 8 fstp qword [esp] push sin_ft call printf add esp, 12
fld qword [lng] fld qword [ref] fsubr st0, st1 sub esp, 8 fstp qword [esp] push diff_ft call printf add esp, 12
push tab_t call printf add esp, 4
mov ecx, -6 .loop: cmp ecx, 6 jg .endloop
push ecx fild dword [esp] fld qword [xv] fmulp fld qword [lng] fsubp fld qword [ref] faddp pop ecx
sub esp, 20 mov dword [esp], ecx fst qword [esp+4]
call st0dr
fptan fxch fld qword [slat] fmulp fxch fpatan
fld qword [rdinv] fmul
fstp qword [esp+12]
push o_ft call printf mov ecx, [esp+4] add esp, 24
inc ecx jmp .loop .endloop:
xor eax, eax ret
section .data
lat: dq 0.0 lng: dq 0.0 ref: dq 0.0 xv: dq 15.0 slat: dq 0.0 drfact: dq 0.01745329251994329576 rdinv: dq 57.29577951308232090712
section .rodata
lat_t: db "Enter latitude: ", 0 lng_t: db "Enter longitude: ", 0 ref_t: db "Enter legal meridian: ", 0
in_ft: db "%lf", 0 newline: db 10, 0
sin_ft: db "sine of latitude: %.3f", 10, 0 diff_ft: db "diff longitude: %.3f", 10, 10, 0
tab_t: db "Hour, sun hour angle, dial hour line angle from 6am to 6pm", 10, 0
o_ft: db "HR= %3d; ",9," HRA=%7.3f; ",9," HLA= %7.3f", 10, 0</lang>
XBasic
<lang xbasic> PROGRAM "sundial" VERSION "0.0001"
IMPORT "xma"
DECLARE FUNCTION Entry()
FUNCTION Entry()
lat! = SINGLE(INLINE$("Enter latitude => ")) lng! = SINGLE(INLINE$("Enter longitude => ")) ref! = SINGLE(INLINE$("Enter legal meridian => ")) PRINT slat! = SIN(lat! * $$PI / 180.0) PRINT " sine of latitude: "; FORMAT$("#.##^^^^", slat!) PRINT " diff longitude: "; FORMAT$("#.###", lng! - ref!) PRINT PRINT "Hour, sun hour angle, dial hour line angle from 6am to 6pm" FOR hour@ = -6 TO 6 hourAngle! = 15 * hour@ hourAngle! = hourAngle! - (lng! - ref!) ' correct for longitude difference hourLineAngle! = ATAN(slat! * TAN(hourAngle! * $$PI / 180.0)) * 180.0 / $$PI PRINT "HR="; FORMAT$("###", hour@); PRINT "; HRA="; FORMAT$("####.###", hourAngle!); PRINT "; HLA="; FORMAT$("####.###", hourLineAngle!) NEXT hour@
END FUNCTION END PROGRAM </lang>
- Output:
Enter latitude => -4.95 Enter longitude => -150.5 Enter legal meridian => -150 sine of latitude: -8.63E-02 diff longitude: -0.500 Hour, sun hour angle, dial hour line angle from 6am to 6pm HR= -6; HRA= -89.500; HLA= 84.225 HR= -5; HRA= -74.500; HLA= 17.283 HR= -4; HRA= -59.500; HLA= 8.334 HR= -3; HRA= -44.500; HLA= 4.847 HR= -2; HRA= -29.500; HLA= 2.795 HR= -1; HRA= -14.500; HLA= 1.278 HR= 0; HRA= 0.500; HLA= -0.043 HR= 1; HRA= 15.500; HLA= -1.371 HR= 2; HRA= 30.500; HLA= -2.910 HR= 3; HRA= 45.500; HLA= -5.018 HR= 4; HRA= 60.500; HLA= -8.671 HR= 5; HRA= 75.500; HLA= -18.451 HR= 6; HRA= 90.500; HLA= 84.225
XPL0
<lang XPL0>inc c:\cxpl\codes; def Pi = 3.14159265358979323846,
Deg2Rad = Pi/180.0, Rad2Deg = 180.0/Pi, Tab = $09;
real Lat, SinLat, Long, Mer; real HA, HLA; \hour angle and hour line angle int H, T; \hour, time [Text(0, "Latitude: "); Lat:= RlIn(0);
Text(0, "Longitude: "); Long:= RlIn(0); Text(0, "Legal meridian: "); Mer:= RlIn(0);
Text(0, " Hour Sun hour angle Dial hour line angle "); Format(4, 3); SinLat:= Sin(Lat*Deg2Rad); for H:= -6 to 6 do
[HA:= float(15 * H); \hour angle is 15 times the hour HA:= HA - (Long-Mer); \ but corrected for longitude difference HLA:= ATan2( SinLat * Sin(HA*Deg2Rad), Cos(HA*Deg2Rad) ) * Rad2Deg; T:= H+12; if T>12 then T:= T-12; if T<10 then ChOut(0, ^ ); IntOut(0, T); Text(0, if H>=0 then "pm " else "am "); RlOut(0, HA); ChOut(0, Tab); RlOut(0, HLA); CrLf(0); ];
]</lang>
- Output:
Latitude: -4.95 Longitude: -150.5 Legal meridian: -150 Hour Sun hour angle Dial hour line angle 6am -89.500 84.225 7am -74.500 17.283 8am -59.500 8.334 9am -44.500 4.847 10am -29.500 2.795 11am -14.500 1.278 12pm 0.500 -0.043 1pm 15.500 -1.371 2pm 30.500 -2.910 3pm 45.500 -5.018 4pm 60.500 -8.671 5pm 75.500 -18.451 6pm 90.500 -95.775
zkl
<lang zkl>//(degree measure)*Degrees => Radian measure //(radian measure)/Degrees => Degree measure const pi=(0.0).pi, toDeg=(0.0).pi/180;
latitude :=ask(0,"Enter latitude: ").toFloat(); longitude:=ask(1,"Enter longitude: ").toFloat(); meridian :=ask(2,"Enter legal meridian: ").toFloat();
sineLatitude:=(latitude * toDeg).sin(); Console.writeln(); Console.writeln("Sine of latitude: ",sineLatitude); Console.writeln("Difference of Longitudes (given longitude - meridian): ",longitude-meridian); Console.writeln();
println("Numbers from 6 AM to 6 PM: "); println("Hour\t\tSun hour angle\t Dial hour line angle");
foreach hour in ([-6..6]){
clockHour:=( if(hour < 0) "%sAM".fmt(hour.abs()) else "%sPM".fmt(hour) ); shr :=15.0*hour - (longitude - meridian); dhla :=(sineLatitude*(shr*toDeg).tan()).atan()/toDeg; Console.writeln("%s\t\t%5.1f\t\t%+7.3f".fmt(clockHour,shr,dhla));
}</lang>
- Output:
$ zkl bbb -4.95 -150.5 -150 Sine of latitude: -0.0862864 Difference of Longitudes (given longitude - meridian): -0.5 Numbers from 6 AM to 6 PM: Hour Sun hour angle Dial hour line angle 6AM -89.5 +84.225 5AM -74.5 +17.283 4AM -59.5 +8.334 3AM -44.5 +4.847 2AM -29.5 +2.795 1AM -14.5 +1.278 0PM 0.5 -0.043 1PM 15.5 -1.371 2PM 30.5 -2.910 3PM 45.5 -5.018 4PM 60.5 -8.671 5PM 75.5 -18.451 6PM 90.5 +84.225
- Output:
$ zkl bbb -4.95 Enter longitude: -150.5 Enter legal meridian: -150 <as above>
ZX Spectrum Basic
<lang zxbasic>10 DEF FN r(x)=x*PI/180 20 DEF FN d(x)=x*180/PI 30 INPUT "Enter latitude (degrees): ";latitude 40 INPUT "Enter longitude (degrees): ";longitude 50 INPUT "Enter legal meridian (degrees): ";meridian 60 PRINT "Latitude: ";latitude 70 PRINT "Longitude:";longitude 80 PRINT "Legal meridian: ";meridian 90 PRINT '" Sun Dial" 100 PRINT "Time hour angle hour line ang." 110 PRINT "________________________________" 120 FOR h=6 TO 18 130 LET hra=15*h-longitude+meridian-180 140 LET hla=FN d(ATN (SIN (FN r(latitude))*TAN (FN r(hra)))) 150 IF ABS (hra)>90 THEN LET hla=hla+180*SGN (hra*latitude) 160 PRINT h;" ";hra;" ";hla 170 NEXT h</lang>
- Programming Tasks
- Sciences
- Mathematics
- 11l
- Ada
- ALGOL 68
- AutoHotkey
- AutoHotkey examples needing attention
- Examples needing attention
- AWK
- BBC BASIC
- C
- C sharp
- C++
- COBOL
- D
- Delphi
- DWScript
- EasyLang
- ERRE
- Euphoria
- F Sharp
- Factor
- Forth
- Fortran
- FreeBASIC
- FutureBasic
- Go
- GW-BASIC
- Haskell
- Icon
- Unicon
- IS-BASIC
- J
- Java
- Julia
- Kotlin
- Liberty BASIC
- LiveCode
- Logo
- Lua
- Mathematica
- Wolfram Language
- Microsoft Small Basic
- МК-61/52
- Modula-2
- NewLISP
- Nim
- Objeck
- OCaml
- Octave
- OoRexx
- Pascal
- Perl
- Phix
- PicoLisp
- PowerShell
- PureBasic
- Python
- Racket
- Raku
- REXX
- Ring
- Ruby
- Run BASIC
- Rust
- Sather
- Scala
- Seed7
- Sidef
- Smalltalk
- Tcl
- Wren
- Wren-fmt
- X86 Assembly
- Libc
- XBasic
- XPL0
- Zkl
- ZX Spectrum Basic