Angle difference between two bearings: Difference between revisions
Angle difference between two bearings (view source)
Revision as of 23:06, 14 March 2017
, 7 years ago→{{header|Fortran}}: Ah, vector analysis...
m (→{{header|Haskell}}: ( applicative inlining of row display function )) |
(→{{header|Fortran}}: Ah, vector analysis...) |
||
Line 132:
=={{header|Fortran}}==
Rather than calculate angle differences and mess about with folding the results into
However, this relies on the unit vectors being accurately so, and their subsequent dot product not exceeding one in size: given the rounding of results with the limited precision actual floating-point arithmetic, there may be problems. Proving that a calculation will not suffer these on a specific computer is difficult, especially as the desire for such a result may mean that any apparent pretext leading to that belief will be seized upon. Because calculations on the IBM pc and similar computers are conducted with 80-bit floating-point arithmetic, rounding errors for 64-bit results are likely to be small, but past experience leads to a "fog of fear" about the precise behaviour of floating-point arithmetic.
As it happens, the test data did not provoke any objections from the ACOSD function, but even so, a conversion to using ''arctan'' instead of ''arccos'' to recover angles would be safer. By using the four-quadrant ''arctan(x,y)'' function, the sign of the angle difference is also delivered and although that result could be in 0°-360° it turns out to be in ±180° as desired. On the other hand, the library of available functions did not include an arctan for complex parameters, so the complex number Z had to be split into its real and imaginary parts, thus requiring two appearances and to avoid repeated calculation, a temporary variable Z is needed. Otherwise, the statement could have been just <code>T = ATAN2D(Z1*CONJG(Z2))</code> and the whole calculation could be effected in one statement, <code>T = ATAN2D(CIS(90 - B1)*CONJG(CIS(90 - B2)))</code> And, since ''cis(t) = exp(i.t)'', <code>T = ATAN2D(EXP(CMPLX(0,90 - B1))*CONJG(EXP(CMPLX(0,90 - B2))))</code> - although using the arithmetic statement function does seem less intimidating.
The source style is F77 (even using the old-style arithmetic statement function) except for the convenience of generic functions taking the type of their parameters to save on the bother of DCMPLX instead of just CMPLX, etc. Floating-point constants in the test data are specified with ~D0, the exponential form that signifies double precision otherwise they would be taken as single precision values. Some compilers offer an option stating that all floating-point constants are to be taken as double precision. REAL*8 precision amounts to about sixteen decimal digits, so some of the supplied values will not be accurately represented, unless something beyond REAL*8 is available. <lang Fortran> SUBROUTINE BDIFF (B1,B2) !Difference B2 - B1, as bearings. All in degrees, not radians.
REAL*8 B1,B2 !Maximum precision, for large-angle folding.
COMPLEX*16 CIS,Z1,Z2,Z !Scratchpads.
CIS(T) = CMPLX(COSD(T),SIND(T)) !Convert an angle into a unit vector.
Z1 = CIS(90 - B1) !Bearings run clockwise from north (y) around to east (x).
Z2 = CIS(90 - B2) !Mathematics runs counterclockwise from x (east).
WRITE (6,10) B1,Z1,B2,Z2,T !Two sets of numbers, and a result.
10 FORMAT (2(F14.4,"(",F9.6,",",F9.6,")"),F9.3) !Two lots, and a tail.
Line 149 ⟶ 153:
REAL*8 B(24) !Just prepare a wad of values.
DATA B/20D0,45D0, -45D0,45D0, -85D0,90D0, -95D0,90D0, !As specified.
1 -45D0,125D0, -45D0,145D0, 29.4803D0,-88.
2 -78.3251D0, -159.036D0,
3 -70099.74233810938D0, 29840.67437876723D0,
4 -165313.6666297357D0, 33693.9894517456D0,
5 1174.8380510598456D0, -154146.66490124757D0,
6 60175.77306795546D0, 42213.07192354373D0/
WRITE (6,1) ("
1 FORMAT (28X,"Bearing calculations, in degrees"//
* 2(
DO I = 1,23,2 !Step through the pairs.
CALL BDIFF(B(I),B(I + 1))
END DO
END</lang>
The output shows the stages:
Line 169 ⟶ 173:
Bearing calculations, in degrees
B1( x, y) B2( x, y)
20.0000( 0.342020, 0.939693) 45.0000( 0.707107, 0.707107) 25.000
-45.0000(-0.707107, 0.707107) 45.0000( 0.707107, 0.707107) 90.000
Line 176 ⟶ 180:
-45.0000(-0.707107, 0.707107) 125.0000( 0.819152,-0.573576) 170.000
-45.0000(-0.707107, 0.707107) 145.0000( 0.573576,-0.819152) -170.000
29.4803( 0.492124, 0.870525) -88.6381(-0.999718, 0.
-78.3251(-0.979312, 0.202358) -159.0360(-0.357781,-0.933805) -80.711
-70099.7423( 0.984016,-0.178078) 29840.6744(-0.633734, 0.773551) -139.584
|