Horizontal sundial calculations: Difference between revisions

m
m (→‎{{header|Wren}}: Minor tidy)
 
(77 intermediate revisions by 33 users not shown)
Line 1:
{{task|sciences}}[[Category:Mathematics]]
[[Category:Mathematics]]
 
;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 [[wp:Jules Verne|Jules Verne]]'s ''[[wp:The Mysterious Island|Lincoln Island]]'', aka ''[[wp:Ernest Legouve Reef|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 [[wp:sundial|sundial]] is a device that measures time by the position of the [[wp:Sun|Sun]]. In common designs such as the horizontal sundial, the sun casts a [[wp:shadow|shadow]] from its ''style'' (also called its [[wp:Gnomon|Gnomon]], a thin rod or a sharp, straight edge)<!-- The style is the time telling edge of the gnomon, Waugh,1973 p29--> onto a flat surface marked with lines indicating the hours of the day. 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 [[wp:true north|true north]] (not the [[wp:North Magnetic Pole|north]] or [[wp:Magnetic South Pole|south magnetic pole]]) and the style's angle with horizontal must equal the sundial's geographical [[wp:latitude|latitude]].
 
Wikipedia: A [[wp:sundial|sundial]] is a device that measures time by the position of the [[wp:Sun|Sun]]. In common designs such as the horizontal sundial, the sun casts a [[wp:shadow|shadow]] from its ''style'' (also called its [[wp:Gnomon|Gnomon]], a thin rod or a sharp, straight edge)<!-- The style is the time telling edge of the gnomon, Waugh,1973 p29--> onto a flat surface marked with lines indicating the hours of the day (also called the [[wp:Sundial#Terminology|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 [[wp:true north|true north]] (not the [[wp:North Magnetic Pole|north]] or [[wp:Magnetic South Pole|south magnetic pole]]) and the style's angle with horizontal must equal the sundial's geographical [[wp:latitude|latitude]].
<br><br>
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight 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))</syntaxhighlight>
 
{{out}}
<pre>
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
</pre>
 
=={{header|Ada}}==
{{trans|ALGOL 68}}
sundial.adb:
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO;
with Ada.Numerics.Elementary_Functions;
procedure Sundial is
Line 53 ⟶ 105:
end;
end loop;
end Sundial;</langsyntaxhighlight>
{{out}}
<pre>Enter latitude: -4.95
Line 90 ⟶ 142:
> Simon
-->
<langsyntaxhighlight lang="algol68">BEGIN
REAL lat, slat, lng, ref;
print ( "Enter latitude => " ); read (lat);
Line 113 ⟶ 165:
new line(stand out)
OD
END</langsyntaxhighlight>
{{out}}
<pre>
Line 138 ⟶ 190:
HR= +6; HRA= +90.500; HLA= +84.225
</pre>
 
=={{header|Arturo}}==
 
{{trans|Nim}}
 
<syntaxhighlight lang="arturo">degToRad: function [deg]-> deg * pi // 180
radToDeg: function [rad]-> rad * 180 // pi
lat: to :floating input "Enter latitude => "
lng: to :floating input "Enter longitude => "
med: to :floating input "Enter legal meridian => "
print ""
slat: sin degToRad lat
 
print " sine of latitude: " ++ to :string .format:".3f" slat
print " diff longitude: " ++ to :string .format:".3f" lng-med
print ""
print "Hour, sun hour angle, dial hour line angle from 6am to 6pm"
loop (neg 6)..6 'h [
hra: med + (to :floating 15*h) - lng
hla: radToDeg atan slat * tan degToRad hra
print "HR=" ++ (to :string .format:"3d" h) ++ "; " ++
"HRA=" ++ (to :string .format:"7.3f" hra) ++ "; " ++
"HLA=" ++ (to :string .format:"7.3f" hla)
]</syntaxhighlight>
 
{{out}}
 
<pre>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</pre>
 
=={{header|AutoHotkey}}==
{{incorrect|AutoHotkey|6AM,5AM,4AM,3AM,2AM,1AM,0PM - use hour+12 instead of abs(hour), I suspect}}
{{trans|F#}}
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.
<langsyntaxhighlight AutoHotkeylang="autohotkey">DllCall("AllocConsole") ; Open a console window for this application
Pi := 4*ATan(1)
,Degrees := Pi/180
Line 173 ⟶ 277:
FileAppend, %clockhour%`t`t%shr%`t`t%dhla%`n, CONOUT$
}
MsgBox close me when done.</langsyntaxhighlight>
{{out}}
<pre>Enter Latitude:-4.95
Line 199 ⟶ 303:
 
=={{header|AWK}}==
<syntaxhighlight lang="awk">
<lang AWK>
# syntax: GAWK -f HORIZONTAL_SUNDIAL_CALCULATIONS.AWK
BEGIN {
Line 217 ⟶ 321:
function dr(x) { return x * 3.14159265 / 180 } # degrees to radians
function rd(x) { return x * 180 / 3.14159265 } # radians to degrees
</syntaxhighlight>
</lang>
<p>output:</p>
<pre>
Line 239 ⟶ 343:
18 90.500 -95.775
</pre>
 
=={{header|BBC BASIC}}==
=={{header|BASIC}}==
==={{header|ANSI BASIC}}===
{{trans|ALGOL-68|ANSI BASIC has a possibility to use degrees in calculations.}}
{{works with|Decimal BASIC}}
<syntaxhighlight lang="basic">
100 REM Horizontal sundial calculations
110 INPUT PROMPT "Enter latitude => ": Lat
120 INPUT PROMPT "Enter longitude => ": Lng
130 INPUT PROMPT "Enter legal meridian => ": Ref
140 PRINT
150 OPTION ANGLE DEGREES
160 LET Slat = SIN(Lat)
170 PRINT " sine of latitude: "; Slat
180 PRINT " diff longitude: "; Lng - Ref
190 PRINT
200 PRINT "Hour, sun hour angle, dial hour line angle from 6am to 6pm"
210 FOR Hour = -6 TO 6
220 LET HourAngle = 15 * Hour
230 LET HourAngle = HourAngle - (Lng - Ref) ! correct for longitude difference
240 LET HourLineAngle = ATN(Slat * TAN(HourAngle))
250 PRINT USING "HR=###; HRA=####.###; HLA=####.###": Hour, HourAngle, HourLineAngle
260 NEXT Hour
270 END
</syntaxhighlight>
{{out}}
<pre>
Enter latitude => -4.95
Enter longitude => -150.5
Enter legal meridian => -150
 
sine of latitude: -8.62863657979234E-2
diff longitude: -.5
 
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= .500; HLA= -.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
</pre>
 
==={{header|BASIC256}}===
<syntaxhighlight lang="basic256">call SolarhoraAngle(-4.95, -150.5, -150.0)
end
 
function rad2deg(theta)
return theta * 180 / pi
end function
 
function deg2rad(theta)
return theta * pi / 180
end function
 
function sign(x)
if x < 0 then sign = -1
if x > 0 then sign = 1
if x = 0 then sign = 0
end function
 
subroutine SolarhoraAngle(latitude, longitude, meridian)
print "Latitude = "; latitude
print "Longitude = "; longitude
print "Meridian = "; meridian
print
print "sine of latitude: "; sin(latitude * pi / 180)
print " diff longitude: "; longitude - meridian
print
print " Time Sun hora angle Dial hora line angle"
for hora = 6 to 18
hra = (15 * hora) - longitude + meridian - 180
hla = rad2deg(atan(sin(deg2rad(latitude)) * tan(deg2rad(hra))))
if abs(hra) > 90 then hla += 180 * sign(hra * latitude)
if hora > 12 then time = hora - 12 : ap$ = " p.m." else time = hora : ap$ = " a.m."
print time; ap$; chr(9); hra; chr(9); chr(9); hla
next hora
end subroutine</syntaxhighlight>
 
==={{header|BBC BASIC}}===
{{works with|BBC BASIC for Windows}}
<langsyntaxhighlight lang="bbcbasic"> INSTALL @lib$+"FNUSING"
INPUT "Enter latitude (degrees) : " latitude
Line 254 ⟶ 444:
IF ABS(hra) > 90 hla += 180 * SGN(hra * latitude)
PRINT FNusing("##.##", hour), FNusing(" ####.### ", hra), FNusing(" ####.###", hla)
NEXT hour</langsyntaxhighlight>
{{out}}
(note the correct '''negative''' value for time 18:00)
Line 275 ⟶ 465:
17.00 75.500 -18.451
18.00 90.500 -95.775</pre>
 
==={{header|Chipmunk Basic}}===
{{works with|Chipmunk Basic|3.6.4}}
<syntaxhighlight lang="qbasic">10 CLS
20 DEF FNR(x) = x * PI/180
30 DEF FND(x) = x * 180/PI
40 INPUT " Enter latitude (degrees): ";latitude
50 INPUT " Enter longitude (degrees): ";longitude
60 INPUT "Enter legal meridian (degrees): ";meridian
70 PRINT
80 PRINT " Time Sun hour angle Dial hour line angle"
90 FOR h = 6 TO 18
100 hra = 15*h-longitude+meridian-180
110 hla = FN D(ARCTAN(SIN(FN R(latitude))*TAN(FN R(hra))))
120 IF ABS(hra) > 90 THEN hla = hla+180*SGN(hra*latitude)
130 PRINT USING "##.##";h;TAB (10)
140 PRINT USING "####.###";hra;TAB (27)
150 PRINT USING "####.###";hla
160 NEXT h
170 END</syntaxhighlight>
{{out}}
<pre>Same as FreeBASIC entry.</pre>
 
==={{header|FreeBASIC}}===
{{trans|BBC BASIC}}
<syntaxhighlight 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</syntaxhighlight>
{{out}}
<pre> 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</pre>
 
==={{header|FutureBasic}}===
<syntaxhighlight lang="futurebasic">window 1
 
def fn rad2deg( theta as double ) as double = theta * 180 / pi
def fn deg2rad( theta as double ) as double = theta * pi / 180
 
local fn SolarHourAngle( latitude as double, longitude as double, meridian as double )
long hour
double hra, hla, t
CFStringRef 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 t = hour - 12 : ap = @" a.m." else t = hour : ap = @" p.m."
print using "##"; t; ap, using "####.##"; hra, using "####.###"; hla
next hour
end fn
 
fn SolarHourAngle( -4.95, -150.5, -150.0 )
 
HandleEvents</syntaxhighlight>
 
Output:
<pre>
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
</pre>
 
==={{header|GW-BASIC}}===
{{trans|ALGOL 68}}
{{works with|PC-BASIC|any}}
<syntaxhighlight 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
</syntaxhighlight>
{{out}}
<pre>
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
</pre>
 
==={{header|IS-BASIC}}===
<syntaxhighlight 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</syntaxhighlight>
 
==={{header|Liberty BASIC}}===
Based on Algol & BBC BASIC versions. Note Liberty BASIC works in radians.
<syntaxhighlight 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</syntaxhighlight>
{{out}}
<pre>
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
</pre>
 
==={{header|Microsoft Small Basic}}===
{{trans|ALGOL-68}}
<syntaxhighlight 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
</syntaxhighlight>
{{out}}
 
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
 
==={{header|Minimal BASIC}}===
{{works with|QBasic}}
{{trans|ALGOL-68}}
<syntaxhighlight lang="gwbasic">
10 REM Horizontal sundial calculations
20 DEF FNM(X) = INT(X*1000+0.5)/1000
30 PRINT "Enter latitude";
40 INPUT L
50 PRINT "Enter longitude";
60 INPUT L1
70 PRINT "Enter legal meridian";
80 INPUT R
90 PRINT
100 LET P = 4*ATN(1)
110 LET S1 = SIN(L*P/180)
120 PRINT " sine of latitude:"; S1
130 PRINT " diff longitude: "; FNM(L1-R)
140 PRINT
150 PRINT "Hour, sun hour angle, dial hour line angle from 6am to 6pm"
160 FOR H = -6 TO 6
170 LET A1 = 15*H
180 REM Correct for longitude difference:
190 LET A1 = A1-(L1-R)
200 LET A2 = ATN(S1*TAN(A1*P/180))*180/P
210 PRINT "HR ="; H;
220 PRINT TAB(9); "HRA ="; FNM(A1);
230 PRINT TAB(24); "HLA ="; FNM(A2)
240 NEXT H
250 END
</syntaxhighlight>
 
==={{header|PureBasic}}===
{{trans|ALGOL 68}}
<syntaxhighlight 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</syntaxhighlight>
{{out}}
<pre>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
</pre>
 
==={{header|Run BASIC}}===
<syntaxhighlight 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</syntaxhighlight>
{{out}}
<pre>
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</pre>
 
==={{header|True BASIC}}===
<syntaxhighlight lang="qbasic">FUNCTION rad2deg(theta)
LET rad2deg = theta*180/PI
END FUNCTION
FUNCTION deg2rad(theta)
LET deg2rad = theta*PI/180
END FUNCTION
FUNCTION signo(x)
IF x > 0 THEN LET signo = 1 ELSE LET signo = -1
END FUNCTION
INPUT prompt "Enter latitude (degrees) : ": latitude ! -4.95
INPUT prompt "Enter longitude (degrees) : ": longitude ! -150.5
INPUT prompt "Enter legal meridian (degrees): ": meridian ! -150.0
PRINT
PRINT "Time Sun hora angle Dial hora line angle"
FOR hora = 6 TO 18
LET hra = (15*hora)-longitude+meridian-180
LET hla = rad2deg(ATN(SIN(deg2rad(latitude))*TAN(deg2rad(hra))))
IF abs(hra) > 90 THEN LET hla = hla+180*signo(hra*latitude)
PRINT USING "## ####.## ####.###": hora, hra, hla
NEXT hora
END</syntaxhighlight>
 
==={{header|XBasic}}===
{{trans|ALGOL-68}}
{{works with|Windows XBasic}}
<syntaxhighlight 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
</syntaxhighlight>
{{out}}
<pre>
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
</pre>
 
==={{header|Yabasic}}===
<syntaxhighlight lang="yabasic">SolarHourAngle(-4.95, -150.5, -150.0)
end
 
sub rad2deg(theta)
return theta * 180 / pi
end sub
 
sub deg2rad(theta)
return theta * pi / 180
end sub
 
sub SolarHourAngle(latitude, longitude, meridian)
local long, hour, hra, hla, time, ap$
print "Latitude = ", latitude
print "Longitude = ", longitude
print "Meridian = ", meridian
print "\nsine of latitude: ", sin(latitude * pi / 180)
print " diff longitude: ", longitude - meridian
print "\n Time Sun hour angle Dial hour line angle"
for hour = 6 to 18
hra = (15 * hour) - longitude + meridian - 180
hla = rad2deg(atan(sin(deg2rad(latitude)) * tan(deg2rad(hra))))
if abs(hra) > 90 hla = hla + 180 * sig(hra * latitude)
if hour > 12 then time = hour - 12 : ap$ = " a.m." else time = hour : ap$ = " p.m." : fi
print time using "##", ap$, chr$(9), hra using "####.##", chr$(9), chr$(9), hla using "####.###"
next hour
end sub</syntaxhighlight>
 
==={{header|ZX Spectrum Basic}}===
{{trans|ERRE}}
<syntaxhighlight 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</syntaxhighlight>
 
=={{header|C}}==
{{trans|ALGOL 68}}
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <math.h>
 
Line 320 ⟶ 1,079:
 
return 0;
}</langsyntaxhighlight>
 
=={{header|C sharp|C#}}==
<langsyntaxhighlight lang="csharp">using System;
 
namespace RosettaCode
Line 354 ⟶ 1,113:
}
}
}</langsyntaxhighlight>
 
=={{header|C++}}==
<syntaxhighlight 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";
}
}
</syntaxhighlight>
{{out}}
<pre>
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
</pre>
 
=={{header|COBOL}}==
{{works with|OpenCOBOL}}
<langsyntaxhighlight lang="cobol">PROGRAM-ID. horizontal-sundial-calc.
 
DATA DIVISION.
Line 411 ⟶ 1,254:
dial-hour-line-angle-disp
END-PERFORM
.</langsyntaxhighlight>
 
{{out}}
Line 440 ⟶ 1,283:
=={{header|D}}==
{{trans|Python}}
<langsyntaxhighlight lang="d">import std.stdio, std.math, std.conv, std.string;
 
double radians(in double x) pure nothrow { return x * (PI / 180); }
Line 467 ⟶ 1,310:
writefln("HR=%3d; HRA=%7.3f; HLA=%7.3f", h, hra, hla);
}
}</langsyntaxhighlight>
{{out|Example run}}
<pre>Enter latitude => -4.95
Line 491 ⟶ 1,334:
HR= 6; HRA= 90.500; HLA= 84.225
</pre>
=={{header|Delphi}}==
See [[#Pascal]]
 
=={{header|DWScript}}==
{{trans|Java}}
<langsyntaxhighlight lang="delphi">procedure PrintSundial(lat, lng, lme : Float);
begin
PrintLn(Format('latitude: %7.2f', [lat]));
Line 516 ⟶ 1,361:
end;
 
PrintSundial(-4.95, -150.5, -150);</langsyntaxhighlight>
{{out}}
<pre>latitude: -4.95
Line 538 ⟶ 1,383:
HR= 5; HRA= 75.500; HLA=-18.451
HR= 6; HRA= 90.500; HLA=-95.775</pre>
 
=={{header|EasyLang}}==
<syntaxhighlight lang="text">
func getn s$ .
write s$
v = number input
print v
return v
.
lat = getn "Enter latitude: "
lng = getn "Enter longitude: "
merid = getn "Enter legal meridian: "
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
.
</syntaxhighlight>
 
=={{header|ERRE}}==
<langsyntaxhighlight ERRElang="erre">PROGRAM SUN_DIAL
 
FUNCTION RAD(X)
Line 568 ⟶ 1,438:
 
END PROGRAM
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 594 ⟶ 1,464:
=={{header|Euphoria}}==
{{works with|OpenEuphoria}}
<syntaxhighlight lang="euphoria">
<lang Euphoria>
include std/console.e
include std/mathcons.e
Line 630 ⟶ 1,500:
 
if getc(0) then end if
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 655 ⟶ 1,525:
=={{header|F_Sharp|F#}}==
{{trans|C#}}
<langsyntaxhighlight lang="fsharp">// Learn more about F# at http://fsharp.net
 
open System
Line 690 ⟶ 1,560:
//To keep the console window open, can be omitted with block comment (" (* comment *) ")
Console.WriteLine("Press any key to continue...")
Console.ReadKey() |> ignore</langsyntaxhighlight>
{{out|Example output}}
<pre>
Line 716 ⟶ 1,586:
6PM 90.5 84.225
Press any key to continue...
</pre>
 
=={{header|Factor}}==
{{trans|Java}}
<syntaxhighlight 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</syntaxhighlight>
{{out}}
<pre>
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
</pre>
 
=={{header|Forth}}==
<langsyntaxhighlight lang="forth">: faccept ( -- f )
pad 32 accept pad swap >float 0= throw ;
: >radians ( deg -- rad ) 180e f/ pi f* ;
Line 737 ⟶ 1,666:
fdup f. ." , "
>radians fsincos fswap frot f* fswap fatan2 >degrees f.
loop fdrop fdrop ;</langsyntaxhighlight>
 
=={{header|Fortran}}==
{{works with|gfortran}} with <tt>-fbackslash</tt> option
<langsyntaxhighlight lang="fortran">program SunDial
 
real :: lat, slat, lng, ref
Line 785 ⟶ 1,714:
end function rd
 
end program SunDial</langsyntaxhighlight>
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 820 ⟶ 1,749:
fmt.Printf("%2.0f %8.3f %8.3f\n", h, hra, hla)
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 847 ⟶ 1,776:
 
=={{header|Haskell}}==
<syntaxhighlight lang="haskell">roundDec :: Int -> Double -> Double
<lang haskell>module Rosetta.HorSunDial where
roundDec d = (/ 10.0 ^ d) . fromIntegral . round . (* 10.0 ^ d)
 
radToDegr = ((180 / pi) *)
roundDec :: Int -> Double -> Double
roundDec d = (/10.0^d). fromIntegral. round. (*10.0^d)
 
radToDegrdegrToRad = ((180/pi / 180) *)
degrToRad = ((pi/180)*)
 
main = do
let lat = -4.95
long = -150.5
legalMerid = -150
sinOfLat = sin $ degrToRad lat
diff = legalMerid - long
(putStrLn . unlines)
putStrLn $ [ "Latitude " ++ show lat
putStrLn $ , "Longitude " ++ show long
putStrLn $ , "Legal meridian " ++ show legalMerid
putStrLn $ , "Sine of latitude " ++ show (roundDec 6 sinOfLat)
putStrLn $ , "Diff longitude " ++ show (-diff)
putStrLn , "hour sun hour angle dial hour line angle"
mapM_ (\h -> ]
mapM_
let sha = diff + 15*h
(\h ->
dhla = radToDegr . atan. (sinOfLat *). tan $ degrToRad sha
in putStrLn $ take 7 (showlet hsha ++= repeatdiff '+ ')15 * h
dhla = radToDegr . atan . (sinOfLat *) . tan $ degrToRad sha
++ take 16 (show (roundDec 3 sha) ++ repeat ' ' )
++ " " ++ showin (roundDecputStrLn 3 dhla)$
take 7 (show h ++ repeat ' ') ++
) [-6,-5..6]</lang>
take 16 (show (roundDec 3 sha) ++ repeat ' ') ++
" " ++ show (roundDec 3 dhla))
[-6,-5 .. 6]</syntaxhighlight>
{{out}}
<pre>*Rosetta.HorSunDial> main
Line 898 ⟶ 1,829:
 
=={{header|Icon}} and {{header|Unicon}}==
<langsyntaxhighlight Iconlang="icon">procedure main()
PrintSundial(-4.95, -150.5, -150);
end
Line 921 ⟶ 1,852:
" HRA=",hra,", HLA=",hla)
}
end</langsyntaxhighlight>
{{out}}
<pre>latitude: -4.95
Line 945 ⟶ 1,876:
 
=={{header|J}}==
<langsyntaxhighlight lang="j">require 'trig'
atan2=: {:@*.@j. NB. arc tangent of y divided by x
Line 959 ⟶ 1,890:
r=.((,. (,. (atan2 *&slat)/@+.@r.&.rfd)) diff + 15&*) i:6
smoutput lbl ,: ('3.0';'7.3';'7.3') 8!:1 r
)</langsyntaxhighlight>
{{out|Example}}
<langsyntaxhighlight lang="j"> horiz _4.95 _150.5 _150
Latitude _4.95
Longitude _150.5
Line 983 ⟶ 1,914:
│ 5 │ 75.500 │-18.451 │
│ 6 │ 90.500 │-95.775 │
└──────┴────────────────┴────────────────────┘</langsyntaxhighlight>
 
=={{header|Java}}==
{{trans|C}} (Substitutes in atan2 for the hour line angle calculation)
<langsyntaxhighlight lang="java">import java.util.Scanner;
 
public class Sundial {
public static void main(String[] args) {
Line 1,008 ⟶ 1,940:
 
for (int h = -6; h <= 6; h++) {
double hla, hra, hraRad;
hra = 15.0 * h;
hra = hra - lng + ref;
Line 1,017 ⟶ 1,949:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>Enter latitude: -4.95
Line 1,041 ⟶ 1,973:
HR= 6; HRA= 90.500; HLA= -95.775</pre>
 
=={{header|Liberty BASICjq}}==
{{works with|jq}}
Based on Algol & BBC BASIC versions. Note Liberty BASIC works in radians.
'''Also works with gojq, the Go implementation of jq.'''
<lang lb>global pi
pi =3.14159265
 
'''Adapted from [[#Wren|Wren]]'''
input "Enter latitude (degrees) : "; latitude ' -4.95
input "Enter longitude (degrees) : "; longitude ' -150.5
input "Enter legal meridian (degrees): "; meridian ' -150.0
 
'''Generic Utilities'''
print
<syntaxhighlight lang=jq>
print "Time Sun hour angle Dial hour line angle"
# `prompts` should be an array defining the prompts, variable names, and their types,
# as exemplified below.
# After all values have been gathered, `get` emits an object defining the bindings.
def get($prompts):
label $out
| foreach range(0;infinite) as $_ ({i:null, imax: ($prompts|length)};
if .i == null then .i = 0
elif .i == .imax then break $out
else .help = null
| first(inputs) as $n
| $prompts[.i].type as $type
| if $type == null or $type == "string"
then .result[$prompts[.i].key] = $n
| .i += 1
elif $type == "number"
then (try ($n|tonumber) catch null) as $n
| if $n then .result[$prompts[.i].key] = $n
| .i += 1
else .help = .i
end
elif $type == "integer"
then if ($n|test("^[0-9]+$"))
then .result[$prompts[.i].key] = ($n|tonumber)
| .i += 1
else .help = .i
end
elif $type|type == "object"
then if $type.regex and ($n | test($type.regex))
then .result[$prompts[.i].key] = $n
| .i += 1
else .help = .i
end
else .
end
end;
(select(.help) | $prompts[.help].help // empty),
if .i < .imax then $prompts[.i].prompt
else .result
end )
;
 
def lpad($len): tostring | ($len - length) as $l | (" " * $l)[:$l] + .;
for hour = 6 TO 18
def rpad($len): tostring | ($len - length) as $l | . + ("0" * $l)[:$l];
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
 
# Input: a string of digits with up to one "."
function rad2deg( theta)
# Output: the corresponding string representation with exactly $n decimal digits
rad2deg =theta *180 /pi
def align_decimal($n):
end function
tostring
| if index(".")
then capture("(?<i>[0-9]*[.])(?<j>[0-9]{0," + ($n|tostring) + "})")
| .i + (.j|rpad($n))
else . + "." + ("0" * $n)
end ;
 
def pi: 4*(1|atan);
function deg2rad( theta)
</syntaxhighlight>
deg2rad =theta *pi /180
'''The Task'''
end function
<syntaxhighlight lang=jq>
def prompts: [
{ prompt: "Enter latitude: ", key: "lat", type: "number", help: "in degrees"},
{ prompt: "Enter longitude: ", key: "lng", type: "number", help: "in degrees"},
{ prompt: "Enter legal meridian: ", key: "ref", type: "number", help: "in degrees"}
];
 
def task:
function sgn( x)
get(prompts)
if x >0 then sgn =1 else sgn =-1
| if type != "object" then . # the prompts
end function
else
((.lat * pi / 180)|sin) as $slat
| (.lng - .ref) as $diff
| "\n sine of latitude : \($slat)",
" diff longitude : \($diff)",
"\nHour, sun hour angle, dial hour line angle from 6am to 6pm",
(range(-6;7) as $h
| (15*$h - $diff) as $hra
| (($hra * pi /180)|sin) as $s
| (($hra * pi /180)|cos) as $c
| (atan2($slat*$s; $c) * 180 / pi) as $hla
| [$h|lpad(3)] + ([$hra, $hla] | map(align_decimal(3)|lpad(7))) | join(" ") )
end;
task
</syntaxhighlight>
'''Invocation''':
The program handles user input errors provided the -R option is specified:
<pre>
jq -nRr -f horizontal-sundial-calculations.jq
</pre>
'''Transcript'''
<pre>
Enter latitude:
-4.95
Enter longitude:
-150.5
Enter legal meridian:
?
in degrees
Enter legal meridian:
-150
 
sine of latitude : -0.08628636579792338
end</lang>
diff longitude : -0.5
 
Hour, sun hour angle, dial hour line angle from 6am to 6pm
-6 89.500 84.224
-5 74.500 17.282
-4 59.500 8.333
-3 44.500 4.846
-2 29.500 2.794
-1 14.500 1.278
0 0.500 0.043
1 15.500 1.370
2 30.500 2.909
3 45.500 5.018
4 60.500 8.671
5 75.500 18.450
6 90.500 95.775
</pre>
 
 
=={{header|Julia}}==
{{trans|Python}}
<syntaxhighlight 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
</syntaxhighlight>
 
{{out}}
<pre>
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
</pre>
 
=={{header|Kotlin}}==
<syntaxhighlight 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))
}
}</syntaxhighlight>
Sample input/output:
{{out}}
<pre>
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
</pre>
 
=={{header|LiveCode}}==
Translation of BASIC versions.
<langsyntaxhighlight LiveCodelang="livecode">on mouseUp
ask "Enter lng,lat,meridian"
if it is empty then exit mouseup
Line 1,103 ⟶ 2,244:
function sgn x
if x >0 then return 1 else return -1
end sgn</langsyntaxhighlight>
 
 
=={{header|Logo}}==
<langsyntaxhighlight lang="logo">type "|Enter latitude: |
make "lat readword
type "|Enter longitude: |
Line 1,119 ⟶ 2,259:
make "hla arctan product sin :lat quotient sin :hra cos :hra
print (sentence "hour :hour ": :hra ", :hla)
]</langsyntaxhighlight>
 
=={{header|Lua}}==
{{trans|Python}}
<syntaxhighlight 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</syntaxhighlight>
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<syntaxhighlight 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</syntaxhighlight>
{{out}}
<pre>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</pre>
 
=={{header|МК-61/52}}==
<syntaxhighlight lang="text">МГ П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 С/П</langsyntaxhighlight>
 
''Input'': ''latitude'' ^ ''longitude'' ^ ''legal meridian'' С/П ... С/П ...; switch of the angle measure set to ''Г''.
Line 1,135 ⟶ 2,333:
''Output'': hour in ''РX'', sun hour angle in ''РY'', dial hour line angle in ''РZ''.
 
=={{header|NimModula-2}}==
{{trans|PythonALGOL-68}}
{{works with|ADW Modula-2|any (Compile with the linker option ''Console Application'').}}
<lang nim>import rdstdin, strutils, math, strfmt
<syntaxhighlight lang="modula2">
MODULE SunDial;
 
FROM STextIO IMPORT
proc radians(x): float = x * Pi / 180
WriteString, WriteLn, SkipLine;
proc degrees(x): float = x * 180 / Pi
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.
</syntaxhighlight>
{{out}}
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
 
=={{header|newLISP}}==
{{trans|Lua}}
<syntaxhighlight 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)</syntaxhighlight>
 
=={{header|Nim}}==
{{trans|Python}}
<syntaxhighlight 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 radians lat.degToRad
echo &" sine of latitude: {slat:.3f}".fmt(slat)
echo &" diff longitude: {lng-med:.3f}".fmt(lng-med)
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 = degrees arctan(slat * tan radians (hra.degToRad)).radToDeg
echo &"HR={h:3d}; HRA={hra:7.3f}; HLA={hla:7.3f}".fmt(h, hra, hla)</langsyntaxhighlight>
 
Output:
{{out}}
<pre>Enter latitude => -4.95
Enter longitude => -150.5
Line 1,182 ⟶ 2,487:
=={{header|Objeck}}==
{{trans|C#}}
<langsyntaxhighlight lang="objeck">
class Sundial {
function : Main(args : String[]) ~ Nil {
Line 1,208 ⟶ 2,513:
}
}
</syntaxhighlight>
</lang>
 
=={{header|OCaml}}==
{{trans|ALGOL 68}}
<langsyntaxhighlight lang="ocaml">let () =
let pi = 4. *. atan 1. in
print_endline "Enter latitude => ";
Line 1,235 ⟶ 2,540:
Printf.printf "HR= %3d; \t HRA=%7.3f; \t HLA= %7.3f\n" h hra hla;
done
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,265 ⟶ 2,570:
 
=={{header|Octave}}==
<langsyntaxhighlight lang="octave">lat = input("Enter latitude: ");
lng = input("Enter longitude: ");
ref = input("Enter legal meridian: ");
Line 1,276 ⟶ 2,581:
hlas = atand( tand(hras) .* slat );
printf("HR= %3d; \t HRA=%7.3f; \t HLA= %7.3f\n",
[ [-6:6]; hras; hlas] );</langsyntaxhighlight>
 
=={{header|OoRexx}}==
{{trans|REXX}}
<syntaxhighlight 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</syntaxhighlight>
{{out}}
Not the same as for REXX anymore as the REXX computer programming example has been updated.
 
=={{header|Pascal}}==
<langsyntaxhighlight lang="pascal">Program SunDial;
 
Const
Line 1,314 ⟶ 2,662:
tab, ' HLA= ', hla:7:3)
end
end.</langsyntaxhighlight>
 
=={{header|Perl 6}}==
{{trans|Raku}}
<lang perl6>sub postfix:<°> ($a) { $a * pi / 180 } # degrees to radians
<syntaxhighlight lang="perl">use utf8;
sub postfix:<®> ($a) { $a * 180 / pi } # radians to degrees
binmode STDOUT, ":utf8";
 
use constant π => 3.14159265;
my $latitude = prompt 'Enter latitude => ';
my $longitude = prompt 'Enter longitude => ';
my $meridian = prompt 'Enter legal meridian => ';
 
sub d2r { $_[0] * π / 180 } # degrees to radians
my $lat_sin = sin( $latitude° );
sub r2d { $_[0] * 180 / π } # radians to degrees
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°';
 
print 'Enter latitude => '; $latitude = <>;
for -6 .. 6 -> $hour {
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 %78.3f %78.3f\n",
($hour + 12) % 12 || 12, ($hour < 0 ?? 'AM' !!: 'PM'), $sun_deg, $line_deg;
}</langsyntaxhighlight>
{{out|Example output}}
<pre>Enter latitude => -4.95
<pre>
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
Line 1,357 ⟶ 2,712:
4 PM 60.500 -8.671
5 PM 75.500 -18.451
6 PM 90.500 -95.775</pre>
</pre>
 
=={{header|Phix}}==
For better behaviour/proper input on pwa/p2js I suppose this should really be a pGUI app.
Copy of [[Horizontal_sundial_calculations#Euphoria|Euphoria]]
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>atom lat = prompt_number("Enter Latitude: ",{})
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
atom lng = prompt_number("Enter Longitude: ",{})
<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>
atom lm = prompt_number("Enter Legal Meridian: ",{})
<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>
puts(1,'\n')
<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>
atom ha, hla
<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>
function Deg2Rad(atom degrees)
<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>
return degrees * PI / 180
<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>
end function
<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>
function Rad2Deg(atom radians)
<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;">"""
return radians * 180 / PI
end function
Sine of latitude: %g
Longitude offset: %g
function atan2(atom y, atom x)
return 2*arctan((sqrt(power(x,2)+power(y,2)) - x)/y)
Hour Sun hour angle Dial hour line angle
end function
-------- -------------- --------------------
"""</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>
atom s_lat = sin(Deg2Rad(lat))
<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>
puts(1,"Hour, Sun Hour Angle, Dial Hour Line Angle\n")
<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>
for hour = -6 to 6 do
<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>
ha = hour * 15 - lng + lm
<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>
atom s = sin(Deg2Rad(ha))
<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>
atom c = cos(Deg2Rad(ha))
<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>
hla = Rad2Deg(atan2(s_lat*s,c))
<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>
printf(1,"%3d %7.3f %7.3f\n",{hour+12,ha,hla})
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end for
<!--</syntaxhighlight>-->
{} = wait_key()</lang>
{{out}}
<pre>
Enter Latitude: (-4.95):
Enter Longitude: (-150.5):
Enter Legal Meridian: (-150):
 
Sine of latitude: -0.086286
Longitude offset: -0.5
 
Hour, Sun Hourhour angle Angle, Dial Hourhour Lineline Angleangle
-------- -------------- --------------------
6 -89.500 84.225
7 6:00am -7489.500 17 84.283225
8 7:00am -5974.500 817.334283
9 8:00am -4459.500 4 8.847334
10 9:00am -2944.500 2 4.795847
11 10:00am -1429.500 1 2.278795
1211:00am -14.500 0.500 -01.043278
1312:00pm 150.500 -10.371043
14 1:00pm 30 15.500 -21.910371
15 2:00pm 45 30.500 -52.018910
16 3:00pm 60 45.500 -85.671018
17 4:00pm 75 60.500 -188.451671
18 5:00pm 90 75.500 -9518.775451
6:00pm 90.500 -95.775
</pre>
 
=={{header|PicoLisp}}==
{{trans|ALGOL 68}}
<langsyntaxhighlight PicoLisplang="picolisp">(load "@lib/math.l")
 
(de prompt (Str . Arg)
Line 1,443 ⟶ 2,812:
(align 8 (round Hra))
"; HLA="
(align 8 (round Hla)) ) ) ) ) ) )</langsyntaxhighlight>
{{out}}
<pre>Enter latitude => -4.95
Line 1,467 ⟶ 2,836:
HR= 6; HRA= 90.500; HLA= 84.225</pre>
 
=={{header|PureBasicPowerShell}}==
<syntaxhighlight lang="powershell">
{{trans|ALGOL 68}}
function Get-Sundial
<lang PureBasic>If OpenConsole()
{
Define.f lat, slat, lng, ref
[CmdletBinding()]
Define.i h
[OutputType([PSCustomObject])]
Print("Enter latitude => "): lat=ValF(Input())
Param
Print("Enter longitude => "): lng=ValF(Input())
(
Print("Enter legal meridian => "): ref=ValF(Input())
[Parameter(Mandatory=$true)]
PrintN("")
[ValidateRange(-90,90)]
[double]
slat=Sin(lat*2*#PI/360)
$Latitude,
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>
{{out}}
<pre>Enter latitude => -4.95
Enter longitude => -150.5
Enter legal meridian => -150
 
sine of latitude: -0.086
diff longitude: -0.500
 
[Parameter(Mandatory=$true)]
Hour, sun hour angle, dial hour line angle from 6am to 6pm
[ValidateRange(-180,180)]
HR= -6; HRA=-89.500; HLA= 84.225
[double]
HR= -5; HRA=-74.500; HLA= 17.283
$Longitude,
HR= -4; HRA=-59.500; HLA= 8.334
 
HR= -3; HRA=-44.500; HLA= 4.847
 
HR= -2; HRA=-29.500; HLA= 2.795
[Parameter(Mandatory=$true)]
HR= -1; HRA=-14.500; HLA= 1.278
[ValidateRange(-180,180)]
HR= 0; HRA= 0.500; HLA= -0.043
[double]
HR= 1; HRA= 15.500; HLA= -1.371
$Meridian
HR= 2; HRA= 30.500; HLA= -2.910
)
HR= 3; HRA= 45.500; HLA= -5.018
 
HR= 4; HRA= 60.500; HLA= -8.671
[double]$sinLat = [Math]::Sin($Latitude*2*[Math]::PI/360)
HR= 5; HRA= 75.500; HLA=-18.451
 
HR= 6; HRA= 90.500; HLA= 84.225
$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
</syntaxhighlight>
{{Out}}
<pre>
 
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
 
</pre>
 
=={{header|Python}}==
{{trans|ALGOL 68}}
<langsyntaxhighlight lang="python">from __future__ import print_function
import math
try: raw_input
Line 1,537 ⟶ 2,938:
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))</langsyntaxhighlight>
{{out}}
<pre>
Line 1,570 ⟶ 2,971:
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.
 
<langsyntaxhighlight Racketlang="racket">#lang racket
 
;; print the table for a given latitude and longitude-offset,
Line 1,647 ⟶ 3,048:
(check-= (to-hla -30 90) -90 1e-5)
(check < (to-hla -30 91) -90)
</syntaxhighlight>
</lang>
{{Out}}
<pre>Welcome to DrRacket, version 5.3.3.5--2013-02-20(5eddac74/d) [3m].
Line 1,674 ⟶ 3,075:
</pre>
 
=={{header|REXXRaku}}==
(formerly Perl 6)
REXX doesn't have the usual trig functions, nor for that matter, a SQRT (square root) function, so these as well as PI were added to this program.
<syntaxhighlight lang="raku" line>sub postfix:<°> ($a) { $a * pi / 180 } # degrees to radians
sub postfix:<®> ($a) { $a * 180 / pi } # radians to degrees
 
my $latitude = prompt 'Enter latitude => ';
No attempt was made to explain the inner workings of the trigonometric functions.
my $longitude = prompt 'Enter longitude => ';
<lang rexx>/*REXX pgm shows: hour, sun hour angle, dial hour line angle, 6am ───► 6pm*/
my $meridian = prompt 'Enter legal meridian => ';
numeric digits 60 /*better overkill then underkill for dig*/
 
my $lat_sin = sin( $latitude° );
parse arg lat lng mer . /*get the optional arguments from the CL*/
say 'Sine of latitude: ', $lat_sin.fmt("%.4f");
/*None specified? Then use the default of Jules */
say 'Longitude offset: ', my $offset = $meridian - $longitude;
/*Verne's Lincoln Island, aka Ernest Legouve Reef.*/
say '=' x 48;
say ' Hour : Sun hour angle° : Dial hour line angle°';
 
for -6 .. 6 -> $hour {
if lat=='' | lat==',' then lat=-4.95 /*Not specified? Then use the default.*/
my $sun_deg = $hour * 15 + $offset;
if lng=='' | lng==',' then lng=-150.5 /* " " " " " " */
my $line_deg = atan2( ( sin($sun_deg°) * $lat_sin ), cos($sun_deg°) )®;
if mer=='' | mer==',' then mer=-150 /* " " " " " " */
printf "%2d %s %7.3f %7.3f\n",
L=max(length(lat), length(lng), length(mer))
($hour + say12) '% 12 || 12, ($hour < 0 ?? latitude:'AM' !! 'PM'), right(lat$sun_deg,L) $line_deg;
}</syntaxhighlight>
say ' longitude:' right(lng,L)
{{out|Example output}}
say ' legal meridian:' right(mer,L)
<pre>
sineLat=sin(d2r(lat))
Enter latitude => -4.95
w1=max(length('hour') ,length('midnight'))+2
Enter longitude => -150.5
w2=max(length('sun hour') ,length('angle'))+2
Enter legal meridian => -150
w3=max(length('dial hour'),length('line angle'))+2
Sine of latitude: -0.0863
indent=left('',30) /*make the presentation prettier. */
Longitude offset: 0.5
say indent center(' ',w1) center('sun hour',w2) center('dial hour' ,w3)
================================================
say indent center('hour',w1) center('angle' ,w2) center('line angle',w3)
Hour : Sun hour angle° : Dial hour line angle°
call sep /*add a separator line for the eyeballs*/
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
</pre>
 
=={{header|REXX}}==
do h=-6 to 6 /*Okey dokey then, let's get busy. */
The REXX language doesn't have the usual trigonometric functions, nor for that matter, a &nbsp; '''sqrt''' &nbsp; (square root) function,
select
<br>so these as well as &nbsp; '''pi''' &nbsp; were added to this program.
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=r2d(Atan(sineLat*tan(d2r(hra))))
say indent center(hc,w1) right(format(hra,,1),w2) right(format(hla,,1),w3)
end /*h*/
 
The &nbsp; ''legal meridian'' &nbsp; is calculated instead of relying on a specified amount.
call sep
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────subroutines───────────────────────────────*/
sep: say indent copies('═',w1) copies('═',w2) copies('═',w3); return
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. */
tan: procedure; parse arg x; _=cos(x); if _=0 then call tanErr; return sin(x)/_
tanErr: call tellErr 'tan(' || x") causes division by zero, X=" || 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
sqrtErr: call tellErr "sqrt(x), X can't be negative, X=" || x
AcosErr: call tellErr 'Acos(x), X must be in the range of -1 ──► +1, X=' ||x
Acos: procedure; arg x; if x<-1|x>1 then call AcosErr; return .5*pi()-Asin(x)
 
The time range was extended &nbsp; (to include quarter─hour times), &nbsp; and to show that the &nbsp;''dial hour line angle''&nbsp; just doesn't
Atan: procedure; arg x; if abs(x)=1 then return pi()/4*sign(x)
<br> change its sign when it exceeds &nbsp;<big>'''±&nbsp;90º'''</big>.
return Asin(x/sqrt(1+x**2))
 
No attempt was made to explain the inner workings of the trigonometric functions.
sin: procedure; arg x; x=r2r(x); numeric fuzz min(5,digits()-3)
<syntaxhighlight lang="rexx">/*REXX program displays: hour, sun hour angle, dial hour line angle, 6am ───► 6pm. */
if abs(x)=pi() then return 0; return .sinCos(x,x,1)
numeric digits length( pi() ) - length(.) /*in case sundial is in polar regions. */
 
cos:parse arg procedure;lat parselng arg. x; x=r2r(x); a=abs(x); hpi=pi /*.5obtain optional arguments from the CL*/
/* ┌───────────◄ None specified? Then use the default*/
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 │ of Jules Verne's Lincoln Island, */
$= left('', 30) if a=pi()*2/3* then return -.5; return aka Ernest Legouve Reef.sinCos(1,1,-1) */
if lat=='' | lat=="," then lat= -4.95 /*Not specified? Then use the default.*/
 
if lng=='' | lng=="," then lng= -150.5 /* " " " " " " */
.sinCos: parse arg z,_,i; x=x*x; p=z
mer= format(lng/15, , 0) * 15 /*calculate legal meridian longitude. */
do k=2 by 2; _=-_*x/(k*(k+i));z=z+_; if z=p then leave; p=z; end; return z
sineLat= sin( d2r(lat) ) /*calculate sine of (radian) latitude. */
 
w1= max( length('hour' ), length("midnight" )) + 2 /*compute the max hour width*/
Asin: procedure; parse arg x; if x<-1 | x>1 then call AsinErr; s=x*x
w2= max( length('sun hour' ), length("angle" )) + 2 /* " " " angle " */
if abs(x)>=.7 then return sign(x)*Acos(sqrt(1-s)); z=x; o=x; p=z
w3= max( length('dial hour'), length("line angle")) + 2 /* " " " lineº " */
do j=2 by 2; o=o*s*(j-1)/j; z=z+o/(j+1); if z=p then leave; p=z; end
L= max( length(lat), length(lng), length(mer) ) /*find the maximum length of 3 numbers.*/
return z
say ' latitude:' right(lat, L) /*display the latitude to the terminal*/
 
pi: pi=, say ' longitude:' right(lng, L) /* " " /*alongitude bit of" an overkill," but hey !!" */
say ' legal meridian:' right(mer, L) /* " legal meridian " " " */
3.1415926535897932384626433832795028841971693993751058209749445923078164062862
say $ center(' ', w1) center("sun hour", w2) center('dial hour' , w3)
return pi /*Note: the real PI subroutine returns PI's accuracy that */
say $ center('hour', w1) center(" angle" , w2) center('line angle', w3)
/*matches the current NUMERIC DIGITS, up to 1 million digits.*/
call sep /*John Machin's formula is used for calculating more digits /*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)*/
sqrt: procedure; parse arg x; if x=0 then return 0; d=digits(); i=; m.=9
hla= r2d( Atan(sineLat * tan(d2r(hra)))) /*this is the heavy lifting calculation*/
numeric digits 9; numeric form; h=d+6; if x<0 then do; x=-x; i='i'; end
parse value formatif abs(x,2,1,,0hra)>90 'E0' then withhla= hla g+ 'E'180 _* .;sign(hra*lat) /*adjust for negative g=gangle*.5'e'_%2/
call docivil j=0 while h>9; m.j=h; h=h%2+1; /*convert the endtime─of─day to /*jcivil time*/
say $ center(hc, w1) right(format(hra,,1), w2-2)@ right(format(hla,,1), w3-5)
do k=j+5 to 0 by -1; numeric digits m.k; g=(g+x/g)*.5; end /*k*/
numeric digits d; return (g/1)i end /*make complex if X < 0.h*/</lang>
call sep /*to help a one─eyed pirate's eyeball. */
'''output'''
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</syntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs:}}
<pre>
latitude: -4.95
Line 1,766 ⟶ 3,211:
legal meridian: -150
sun hour dial hour
hour angle angle line angle
══════════ ══════════ ════════════
6 am -89.5 84.2
5 am -74.5 17.3
4 am -59.5 8.3
3 am -44.5 4.8
2 am -29.5 2.8
1 am -14.5 1.3
noon 0.5 0.0
1 pm 15.5 -1.4
2 pm 30.5 -2.9
3 pm 45.5 -5.0
4 pm 60.5 -8.7
5 pm 75.5 -18.5
6 pm 90.5 84.2
══════════ ══════════ ════════════
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
══════════ ══════════ ════════════
</pre>
 
=={{header|Ring}}==
<syntaxhighlight 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
</syntaxhighlight>
Output:
<pre>
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
</pre>
 
Line 1,787 ⟶ 3,324:
{{trans|ALGOL 68}}
{{trans|Python}}
<langsyntaxhighlight lang="ruby">include Math
DtoR = PI/180
 
Line 1,809 ⟶ 3,346:
hla = atan( slat * tan( hra * DtoR ))/ DtoR
puts "HR =%3d; HRA =%7.3f; HLA =%7.3f" % [h, hra, hla]
end</langsyntaxhighlight>
{{out}}
<pre>
Line 1,835 ⟶ 3,372:
</pre>
 
=={{header|Run BASICRust}}==
<syntaxhighlight lang="rust">
<lang runbasic>global pi
use std::io;
pi = 22 / 7
struct SundialCalculation {
hour_angle: f64,
print "Enter latitude (degrees) : "; :input latitude ' -4.95
hour_line_angle: f64,
print "Enter longitude (degrees) : "; :input longitude ' -150.5
}
print "Enter legal meridian (degrees): "; :input meridian ' -150.0
 
fn get_input(prompt: &str) -> Result<f64, Box<dyn std::error::Error>> {
print
println!("{}", prompt);
print "Time Sun hour angle Dial hour line angle"
let mut input = String::new();
let stdin = io::stdin();
for hour = 6 TO 18
stdin.read_line(&mut input)?;
hra = (15 * hour) - longitude + meridian -180
Ok(input.trim().parse::<f64>()?)
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)
fn calculate_sundial(hour: i8, lat: f64, lng: f64, meridian: f64) -> SundialCalculation {
next hour
let diff = lng - meridian;
let hour_angle = f64::from(hour) * 15. - diff;
function rad2deg( theta)
let hour_line_angle = (hour_angle.to_radians().tan() * lat.to_radians().sin())
rad2deg =theta *180 /pi
.atan()
end function
.to_degrees();
 
function deg2rad( theta)
SundialCalculation {
deg2rad =theta *pi /180
hour_angle,
end function
hour_line_angle,
}
function sgn( x)
}
if x >0 then sgn =1 else sgn =-1
fn main() -> Result<(), Box<dyn std::error::Error>> {
end function
let lat = get_input("Enter latitude => ")?;
end</lang>
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(())
}
 
</syntaxhighlight>
{{out}}
<pre>
Enter latitude: -4.95 =>
-4.95
Enter longitude: -150.5
Enter legallongitude meridian: -150 =>
-150.5
 
Enter legal meridian =>
Time Sun hour angle Dial hour line angle
-150
6 -89.50 84.606
Sine of latitude: -0.08629
7 -74.50 17.316
8 Diff longitude: -590.505 8.342
Hrs Angle Hour Line Angle
9 -44.50 4.850
10 6pm -2989.50 5 2+84.79622483
11 7pm -1474.50 5 1+17.27928293
12 8pm 0-59.505 -0+8.04333371
13 9pm 15-44.505 -1+4.37184671
14 10pm 30-29.505 -+2.91179487
15 11pm 45-14.505 -5+1.02127835
16 12pm 600.50 5 -80.68004314
17 1pm 7515.505 -181.48837079
18 2pm 9030.505 -962.224</pre>90964
3pm 45.5 -5.01802
4pm 60.5 -8.67140
5pm 75.5 -18.45100
6pm 90.5 +84.22483
</pre>
 
=={{header|Sather}}==
<langsyntaxhighlight lang="sather">class MAIN is
 
getvalue(s:STR):FLT is
Line 1,918 ⟶ 3,483:
end;
end;
end;</langsyntaxhighlight>
 
=={{header|Scala}}==
<syntaxhighlight 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")
}
 
}</syntaxhighlight>
 
=={{header|Seed7}}==
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
include "float.s7i";
include "math.s7i";
Line 1,957 ⟶ 3,551:
"; HLA= " <& hla digits 3 lpad 7);
end for;
end func;</langsyntaxhighlight>
{{out}}
<pre>Enter latitude: -4.95
<pre>
Enter latitude: -4.95
Enter longitude: -150.5
Enter legal meridian: -150
Line 1,980 ⟶ 3,573:
HR= 4; HRA= 60.500; HLA= -8.671
HR= 5; HRA= 75.500; HLA= -18.451
HR= 6; HRA= 90.500; HLA= 84.225</pre>
 
=={{header|Sidef}}==
{{trans|Raku}}
<syntaxhighlight 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)
}</syntaxhighlight>
{{out}}
<pre>
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
</pre>
 
=={{header|Smalltalk}}==
{{works with|GNU Smalltalk}}
<langsyntaxhighlight lang="smalltalk">|lat slat lng ref hra hla pi|
pi := 1 arcTan * 4.
'Enter latitude: ' display. lat := stdin nextLine asNumber.
Line 2,001 ⟶ 3,642:
hla := (hra degreesToRadians tan * slat) arcTan radiansToDegrees.
('HR= %1; %4 HRA=%2; %4 HLA= %3' % { h. hra. hla. $<9> }) displayNl.
]</langsyntaxhighlight>
 
=={{header|Tcl}}==
{{trans|ALGOL 68}}
<langsyntaxhighlight lang="tcl">set PI 3.1415927
fconfigure stdout -buffering none
puts -nonewline "Enter latitude => "; gets stdin lat
Line 2,023 ⟶ 3,664:
set hla [expr {atan($slat * tan($hra*$PI/180)) * 180/$PI}]
puts [format "HR=%+3d; HRA=%+8.3f; HLA=%+8.3f" $h $hra $hla]
}</langsyntaxhighlight>
{{out|Sample output}}
<pre>
Line 2,047 ⟶ 3,688:
HR= +5; HRA= +75.500; HLA= -18.451
HR= +6; HRA= +90.500; HLA= +84.225
</pre>
 
=={{header|Wren}}==
{{trans|Go}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">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)
}</syntaxhighlight>
 
{{out}}
<pre>
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
</pre>
 
Line 2,053 ⟶ 3,752:
{{libheader|libc}}
It must be linked with the C standard library and startup code.
<langsyntaxhighlight lang="asm"> global main
extern printf, scanf
 
Line 2,189 ⟶ 3,888:
 
o_ft:
db "HR= %3d; ",9," HRA=%7.3f; ",9," HLA= %7.3f", 10, 0</langsyntaxhighlight>
 
=={{header|XPL0}}==
<langsyntaxhighlight XPL0lang="xpl0">inc c:\cxpl\codes;
def Pi = 3.14159265358979323846,
Deg2Rad = Pi/180.0,
Line 2,217 ⟶ 3,916:
RlOut(0, HA); ChOut(0, Tab); RlOut(0, HLA); CrLf(0);
];
]</langsyntaxhighlight>
 
{{out}}
Line 2,243 ⟶ 3,942:
=={{header|zkl}}==
{{trans|F#}}
<langsyntaxhighlight lang="zkl">//(degree measure)*Degrees => Radian measure
//(radian measure)/Degrees => Degree measure
const pi=(0.0).pi, toDeg=(0.0).pi/180;
Line 2,265 ⟶ 3,964:
dhla :=(sineLatitude*(shr*toDeg).tan()).atan()/toDeg;
Console.writeln("%s\t\t%5.1f\t\t%+7.3f".fmt(clockHour,shr,dhla));
}</langsyntaxhighlight>
{{out}}
<pre>
9,490

edits