Angle difference between two bearings: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|Haskell}}: Add Fortran.)
m (→‎JS ES6: Layout, function name)
Line 378: Line 378:


<lang JavaScript>(() => {
<lang JavaScript>(() => {
const
[Pi, sin, cos, acos] =
['PI', 'sin', 'cos', 'acos']
.map(k => Math[k]),
degRad = x => Pi * x / 180.0,
radDeg = x => 180.0 * x / Pi;



// relBearing :: Radians -> Radians -> Radians
// bearingDelta :: Radians -> Radians -> Radians
const relBearing = (ar, br) => {
const bearingDelta = (ar, br) => {
const [ax, ay] = [sin(ar), cos(ar)], [bx, by] = [sin(br), cos(br)],
const
[ax, ay] = [sin(ar), cos(ar)],
[bx, by] = [sin(br), cos(br)],


// Cross-product > 0 ?
// Cross-product > 0 ?
sign = ((ay * bx) - (by * ax)) > 0 ? +1 : -1;
sign = ((ay * bx) - (by * ax)) > 0 ? +1 : -1;


// Sign * dot-product
// Sign * dot-product
return sign * acos((ax * bx) + (ay * by));
return sign * acos((ax * bx) + (ay * by));
}
};


// Pi, sin, cos, acos :: Function
// TEST
const [Pi, sin, cos, acos] = ['PI', 'sin', 'cos', 'acos']
.map(k => Math[k]),
degRad = x => Pi * x / 180.0,
radDeg = x => 180.0 * x / Pi;


// TEST ------------------------------------------------------------------


// justifyRight :: Int -> Char -> Text -> Text
// justifyRight :: Int -> Char -> Text -> Text
Line 407: Line 405:
.slice(-n)
.slice(-n)
) : strText;
) : strText;



// showMap :: Degrees -> Degrees -> String
// showMap :: Degrees -> Degrees -> String
const showMap = (da, db) =>
const showMap = (da, db) =>
justifyRight(6, ' ', `${da}° +`) +
justifyRight(6, ' ', `${da}° +`) +
justifyRight(11, ' ',` ${db}° -> `) +
justifyRight(11, ' ', ` ${db}° -> `) +
justifyRight(7, ' ', `${(radDeg(relBearing(degRad(da), degRad(db))))
justifyRight(7, ' ', `${(radDeg(bearingDelta(degRad(da), degRad(db))))
.toPrecision(4)}°`);
.toPrecision(4)}°`);


Line 426: Line 423:
.join('\n');
.join('\n');
})();</lang>
})();</lang>

{{Out}}
{{Out}}
<pre>
<pre>

Revision as of 11:20, 13 March 2017

Angle difference between two bearings is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Finding the angle between two bearings is often confusing.[1]

Task

We need to find the angle which is the result of the subtraction b2-b1, where b1 and b2 are both bearings. Input bearings are expressed by numbers in the range -180 to +180 degrees. The result must also be expressed in the range +180 to -180 degrees. Compute the angle for the following pairs:

  • 20 degrees (b1) and 45 degrees (b2)
  • -45 and 45
  • -85 and 90
  • -95 and 90
  • -45 and 125
  • -45 and 145
  • 29.4803 and -88.6381
  • -78.3251 and -159.036

Optional extra: allow the input bearings to be any (finite) value. Test cases:

  • -70099.74233810938 and 29840.67437876723
  • -165313.6666297357 and 33693.9894517456
  • 1174.8380510598456 and -154146.66490124757
  • 60175.77306795546 and 42213.07192354373

AWK

<lang AWK>

  1. syntax: GAWK -f ANGLE_DIFFERENCE_BETWEEN_TWO_BEARINGS.AWK

BEGIN {

   fmt = "%11s %11s %11s\n"
   while (++i <= 11) { u = u "-" }
   printf(fmt,"B1","B2","DIFFERENCE")
   printf(fmt,u,u,u)
   main(20,45)
   main(-45,45)
   main(-85,90)
   main(-95,90)
   main(-45,125)
   main(-45,145)
   main(29.4803,-88.6381)
   main(-78.3251,-159.036)
   main(-70099.74233810938,29840.67437876723)
   main(-165313.6666297357,33693.9894517456)
   main(1174.8380510598456,-154146.66490124757)
   main(60175.77306795546,42213.07192354373)
   exit(0)

} function main(b1,b2) {

   printf("%11.2f %11.2f %11.2f\n",b1,b2,angle_difference(b1,b2))

} function angle_difference(b1,b2, r) {

   r = (b2 - b1) % 360
   if (r < -180) {
     r += 360
   }
   if (r >= 180) {
     r -= 360
   }
   return(r)

} </lang>

Output:
         B1          B2  DIFFERENCE
----------- ----------- -----------
      20.00       45.00       25.00
     -45.00       45.00       90.00
     -85.00       90.00      175.00
     -95.00       90.00     -175.00
     -45.00      125.00      170.00
     -45.00      145.00     -170.00
      29.48      -88.64     -118.12
     -78.33     -159.04      -80.71
  -70099.74    29840.67     -139.58
 -165313.67    33693.99      -72.34
    1174.84  -154146.66     -161.50
   60175.77    42213.07       37.30

C++

<lang cpp>#include <cmath>

  1. include <iostream>

using namespace std;

double getDifference(double b1, double b2) { double r = fmod(b2 - b1, 360.0); if (r < -180.0) r += 360.0; if (r >= 180.0) r -= 360.0; return r; }

int main() { cout << "Input in -180 to +180 range" << endl; cout << getDifference(20.0, 45.0) << endl; cout << getDifference(-45.0, 45.0) << endl; cout << getDifference(-85.0, 90.0) << endl; cout << getDifference(-95.0, 90.0) << endl; cout << getDifference(-45.0, 125.0) << endl; cout << getDifference(-45.0, 145.0) << endl; cout << getDifference(-45.0, 125.0) << endl; cout << getDifference(-45.0, 145.0) << endl; cout << getDifference(29.4803, -88.6381) << endl; cout << getDifference(-78.3251, -159.036) << endl;

cout << "Input in wider range" << endl; cout << getDifference(-70099.74233810938, 29840.67437876723) << endl; cout << getDifference(-165313.6666297357, 33693.9894517456) << endl; cout << getDifference(1174.8380510598456, -154146.66490124757) << endl; cout << getDifference(60175.77306795546, 42213.07192354373) << endl;

return 0; }</lang>

Output:
Input in -180 to +180 range
25
90
175
-175
170
-170
170
-170
-118.118
-80.7109
Input in wider range
-139.583
-72.3439
-161.503
37.2989

Fortran

Rather than calculate angle differences and mess about with folding the results into +-180 and getting the sign right, why not use some mathematics? These days, trigonometrical functions are calculated swiftly by specialised hardware (well, microcode), and with the availability of functions working in degrees, matters are eased further nor is precision lost in converting from degrees to radians. So, the first step is to convert a bearing into an (x,y) unit vector via function CIS(t) = cos(t) + i.sin(t), which will handle all the annoyance of bearings specified in values above 360. Then, using the dot product of the two vectors allows the cosine of the angle to be known, and the cross product determines the sign.

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	!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).
       T = ACOSD(REAL(Z1)*REAL(Z2) + AIMAG(Z1)*AIMAG(Z2))	!Dot product: Z1.Z2 = cos(T) for unit vectors.
       IF (REAL(Z1)*AIMAG(Z2) .GT. REAL(Z2)*AIMAG(Z1)) T = -T	!Adjust the sign via the cross product.
       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.
     END SUBROUTINE BDIFF	!Having functions in degrees saves some bother.
     PROGRAM ORIENTED
     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.6381,
    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) "B1","x","y","B2","x","y","B2 - B1"
   1 FORMAT (28X,"Bearing calculations, in degrees"//
    * 2(A14,"(",A9,",",A9,")"),A9)	!Compare format 10, above.
    
     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:

                            Bearing calculations, in degrees

            B1(        x,        y)            B2(        x,        y)  B2 - B1
       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
      -85.0000(-0.996195, 0.087156)       90.0000( 1.000000, 0.000000)  175.000
      -95.0000(-0.996195,-0.087156)       90.0000( 1.000000, 0.000000) -175.000
      -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.023768) -118.118
      -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
  -165313.6666(-0.959667, 0.281138)    33693.9895(-0.559023,-0.829152)  -72.340
     1174.8381( 0.996437,-0.084339)  -154146.6649(-0.918252, 0.395996) -161.510
    60175.7731( 0.826820, 0.562467)    42213.0719( 0.998565,-0.053561)   37.297

Haskell

<lang Haskell>import Text.Printf

type Radians = Float

type Degrees = Float

angleBetweenDegrees :: Degrees -> Degrees -> Degrees angleBetweenDegrees a b = degrees $ relBearing (radians a) (radians b)

relBearing :: Radians -> Radians -> Radians relBearing a b -- sign * dot-product

= sign * acos ((ax * bx) + (ay * by))
 where
   (ax, ay) = (sin a, cos a)
   (bx, by) = (sin b, cos b)
   sign -- cross-product > 0 ?
    =
     if ((ay * bx) - (by * ax)) > 0
       then 1
       else (-1)

degrees :: Radians -> Degrees degrees = (/ pi) . (180 *)

radians :: Degrees -> Radians radians = (/ 180) . (pi *)

main :: IO () main =

 mapM_ putStrLn $
 displayRow <$>
 [ (20.0, 45.0)
 , (-45.0, 45.0)
 , (-85.0, 90.0)
 , (-95.0, 90.0)
 , (-45.0, 125.0)
 , (-45.0, 145.0)
 ]
 where
   displayRow (x, y) =
     printf "%6.2f° + %6.2f°  ->  %7.2f°" x y $ angleBetweenDegrees x y</lang>
Output:
 20.00° +  45.00°  ->    25.00°
-45.00° +  45.00°  ->    90.00°
-85.00° +  90.00°  ->   175.00°
-95.00° +  90.00°  ->  -175.00°
-45.00° + 125.00°  ->   170.00°
-45.00° + 145.00°  ->  -170.00°

J

<lang j>relativeBearing=: -&360^:(180&<)@(360 | 720 + -~)/</lang> <lang j>tests=: _99&".;._2 noun define 20 45 -45 45 -85 90 -95 90 -45 125 -45 145 29.4803 -88.6381 -78.3251 -159.036 -70099.74233810938 29840.67437876723 -165313.6666297357 33693.9894517456 1174.8380510598456 -154146.66490124757 60175.77306795546 42213.07192354373 )

  tests ,. relativeBearing"1 tests
     20       45       25
    _45       45       90
    _85       90      175
    _95       90     _175
    _45      125      170
    _45      145     _170
29.4803 _88.6381 _118.118

_78.3251 _159.036 _80.7109 _70099.7 29840.7 _139.583

_165314    33694 _72.3439
1174.84  _154147 _161.503
60175.8  42213.1  37.2989</lang>

Java

Translation of: C++

<lang java>public class AngleDifference {

public static double getDifference(double b1, double b2) { double r = (b2 - b1) % 360.0; if (r < -180.0) r += 360.0; if (r >= 180.0) r -= 360.0; return r; }

public static void main(String[] args) { System.out.println("Input in -180 to +180 range"); System.out.println(getDifference(20.0, 45.0)); System.out.println(getDifference(-45.0, 45.0)); System.out.println(getDifference(-85.0, 90.0)); System.out.println(getDifference(-95.0, 90.0)); System.out.println(getDifference(-45.0, 125.0)); System.out.println(getDifference(-45.0, 145.0)); System.out.println(getDifference(-45.0, 125.0)); System.out.println(getDifference(-45.0, 145.0)); System.out.println(getDifference(29.4803, -88.6381)); System.out.println(getDifference(-78.3251, -159.036));

System.out.println("Input in wider range"); System.out.println(getDifference(-70099.74233810938, 29840.67437876723)); System.out.println(getDifference(-165313.6666297357, 33693.9894517456)); System.out.println(getDifference(1174.8380510598456, -154146.66490124757)); System.out.println(getDifference(60175.77306795546, 42213.07192354373)); } }</lang>

Output:
Input in -180 to +180 range
25.0
90.0
175.0
-175.0
170.0
-170.0
170.0
-170.0
-118.1184
-80.7109
Input in wider range
-139.58328312338563
-72.34391851868713
-161.50295230740448
37.29885558826936

JavaScript

ES5

This approach should be reliable but it is also very inefficient.

<lang javascript>function relativeBearing(b1Rad, b2Rad) { b1y = Math.cos(b1Rad); b1x = Math.sin(b1Rad); b2y = Math.cos(b2Rad); b2x = Math.sin(b2Rad); crossp = b1y * b2x - b2y * b1x; dotp = b1x * b2x + b1y * b2y; if(crossp > 0.) return Math.acos(dotp); return -Math.acos(dotp); }

function test() { var deg2rad = 3.14159265/180.0; var rad2deg = 180.0/3.14159265; return "Input in -180 to +180 range\n" +relativeBearing(20.0*deg2rad, 45.0*deg2rad)*rad2deg+"\n" +relativeBearing(-45.0*deg2rad, 45.0*deg2rad)*rad2deg+"\n" +relativeBearing(-85.0*deg2rad, 90.0*deg2rad)*rad2deg+"\n" +relativeBearing(-95.0*deg2rad, 90.0*deg2rad)*rad2deg+"\n" +relativeBearing(-45.0*deg2rad, 125.0*deg2rad)*rad2deg+"\n" +relativeBearing(-45.0*deg2rad, 145.0*deg2rad)*rad2deg+"\n"

+relativeBearing(29.4803*deg2rad, -88.6381*deg2rad)*rad2deg+"\n" +relativeBearing(-78.3251*deg2rad, -159.036*deg2rad)*rad2deg+"\n"

+ "Input in wider range\n" +relativeBearing(-70099.74233810938*deg2rad, 29840.67437876723*deg2rad)*rad2deg+"\n" +relativeBearing(-165313.6666297357*deg2rad, 33693.9894517456*deg2rad)*rad2deg+"\n" +relativeBearing(1174.8380510598456*deg2rad, -154146.66490124757*deg2rad)*rad2deg+"\n" +relativeBearing(60175.77306795546*deg2rad, 42213.07192354373*deg2rad)*rad2deg+"\n";

}</lang>

Output:
Input in -180 to +180 range
25.000000000000004
90
174.99999999999997
-175.00000041135993
170.00000000000003
-170.00000041135996
-118.1184
-80.71089999999998
Input in wider range
-139.5833974814558
-72.34414600076728
-161.50277501127033
37.2988761562732

ES6

<lang JavaScript>(() => {

   // bearingDelta :: Radians -> Radians -> Radians
   const bearingDelta = (ar, br) => {
       const [ax, ay] = [sin(ar), cos(ar)], [bx, by] = [sin(br), cos(br)],
       // Cross-product > 0 ?
       sign = ((ay * bx) - (by * ax)) > 0 ? +1 : -1;
       // Sign * dot-product
       return sign * acos((ax * bx) + (ay * by));
   };
   // Pi, sin, cos, acos :: Function
   const [Pi, sin, cos, acos] = ['PI', 'sin', 'cos', 'acos']
   .map(k => Math[k]),
       degRad = x => Pi * x / 180.0,
       radDeg = x => 180.0 * x / Pi;


   // TEST ------------------------------------------------------------------
   // justifyRight :: Int -> Char -> Text -> Text
   const justifyRight = (n, cFiller, strText) =>
       n > strText.length ? (
           (cFiller.repeat(n) + strText)
           .slice(-n)
       ) : strText;
   // showMap :: Degrees -> Degrees -> String
   const showMap = (da, db) =>
       justifyRight(6, ' ', `${da}° +`) +
       justifyRight(11, ' ', ` ${db}°  ->  `) +
       justifyRight(7, ' ', `${(radDeg(bearingDelta(degRad(da), degRad(db))))
           .toPrecision(4)}°`);
   return [
           [20, 45],
           [-45, 45],
           [-85, 90],
           [-95, 90],
           [-45, 125],
           [-45, 145]
       ].map(xy => showMap(...xy))
       .join('\n');

})();</lang>

Output:
 20° +  45°  ->   25.00°
-45° +  45°  ->   90.00°
-85° +  90°  ->   175.0°
-95° +  90°  ->  -175.0°
-45° + 125°  ->   170.0°
-45° + 145°  ->  -170.0°

Perl 6

Works with: Rakudo version 2016.11

<lang perl6>sub infix:<∠> (Real $b1, Real $b2) {

  (my $b = ($b2 - $b1 + 720) % 360) > 180 ?? $b - 360 !! $b;

}

  1. TESTING

for 20, 45,

  -45, 45,
  -85, 90,
  -95, 90,
  -45, 125,
  -45, 145,
  29.4803, -88.6381,
  -78.3251, -159.036,
  -70099.74233810938, 29840.67437876723,
  -165313.6666297357, 33693.9894517456,
  1174.8380510598456, -154146.66490124757,
  60175.77306795546, 42213.07192354373
 -> $b1, $b2 { say "$b1 ∠ $b2 = ", $b1 ∠ $b2 }</lang>
Output:
20 ∠ 45 = 25
-45 ∠ 45 = 90
-85 ∠ 90 = 175
-95 ∠ 90 = -175
-45 ∠ 125 = 170
-45 ∠ 145 = -170
29.4803 ∠ -88.6381 = -118.1184
-78.3251 ∠ -159.036 = -80.7109
-70099.74233810938 ∠ 29840.67437876723 = -139.58328312339
-165313.6666297357 ∠ 33693.9894517456 = -72.3439185187
1174.8380510598456 ∠ -154146.66490124757 = -161.5029523074156
60175.77306795546 ∠ 42213.07192354373 = 37.29885558827

Python

Translation of: C++

<lang python>from __future__ import print_function

def getDifference(b1, b2): r = (b2 - b1) % 360.0 # Python modulus has same sign as divisor, which is positive here, # so no need to consider negative case if r >= 180.0: r -= 360.0 return r

if __name__ == "__main__": print ("Input in -180 to +180 range") print (getDifference(20.0, 45.0)) print (getDifference(-45.0, 45.0)) print (getDifference(-85.0, 90.0)) print (getDifference(-95.0, 90.0)) print (getDifference(-45.0, 125.0)) print (getDifference(-45.0, 145.0)) print (getDifference(-45.0, 125.0)) print (getDifference(-45.0, 145.0)) print (getDifference(29.4803, -88.6381)) print (getDifference(-78.3251, -159.036))

print ("Input in wider range") print (getDifference(-70099.74233810938, 29840.67437876723)) print (getDifference(-165313.6666297357, 33693.9894517456)) print (getDifference(1174.8380510598456, -154146.66490124757)) print (getDifference(60175.77306795546, 42213.07192354373))</lang>

Output:
Input in -180 to +180 range
25.0
90.0
175.0
-175.0
170.0
-170.0
170.0
-170.0
-118.11840000000001
-80.71089999999998
Input in wider range
-139.58328312338563
-72.34391851868713
-161.50295230740448
37.29885558826936

Ruby

Translation of: C++

<lang ruby>def getDifference(b1, b2) r = (b2 - b1) % 360.0 # Ruby modulus has same sign as divisor, which is positive here, # so no need to consider negative case if r >= 180.0 r -= 360.0 end return r end

if __FILE__ == $PROGRAM_NAME puts "Input in -180 to +180 range" puts getDifference(20.0, 45.0) puts getDifference(-45.0, 45.0) puts getDifference(-85.0, 90.0) puts getDifference(-95.0, 90.0) puts getDifference(-45.0, 125.0) puts getDifference(-45.0, 145.0) puts getDifference(-45.0, 125.0) puts getDifference(-45.0, 145.0) puts getDifference(29.4803, -88.6381) puts getDifference(-78.3251, -159.036)

puts "Input in wider range" puts getDifference(-70099.74233810938, 29840.67437876723) puts getDifference(-165313.6666297357, 33693.9894517456) puts getDifference(1174.8380510598456, -154146.66490124757) puts getDifference(60175.77306795546, 42213.07192354373) end</lang>

Output:
Input in -180 to +180 range
25.0
90.0
175.0
-175.0
170.0
-170.0
170.0
-170.0
-118.11840000000001
-80.71089999999998
Input in wider range
-139.58328312338563
-72.34391851868713
-161.50295230740448
37.29885558826936

Racket

see my comments in discussion regards bearing-heading or vice versa

<lang racket>#lang racket (define (% a b) (- a (* b (truncate (/ a b)))))

(define (bearing- bearing heading)

 (- (% (+ (% (- bearing heading) 360) 540) 360) 180))

(module+ main

 (bearing- 20 45)
 (bearing- -45 45)
 (bearing- -85 90)
 (bearing- -95 90)
 (bearing- -45 125)
 (bearing- -45 145)
 (bearing- 29.4803 -88.6381)
 (bearing- -78.3251 -159.036)
 (bearing- -70099.74233810938 29840.67437876723)
 (bearing- -165313.6666297357 33693.9894517456)
 (bearing- 1174.8380510598456 -154146.66490124757)
 (bearing- 60175.77306795546 42213.07192354373))

(module+ test

 (require rackunit)
 (check-equal? (% 7.5 10) 7.5)
 (check-equal? (% 17.5 10) 7.5)
 (check-equal? (% -7.5 10) -7.5)
 (check-equal? (% -17.5 10) -7.5))</lang>
Output:
-25
-90
-175
175
-170
170
118.11839999999995
80.71090000000004
139.58328312338563
72.34391851868713
161.50295230740448
-37.29885558826936

REXX

A little extra coding was added for a better visual presentation;   the angles were centered, the answers were aligned. <lang rexx>/*REXX pgm calculates the difference between 2 angles (degrees), normalizes the result. */ numeric digits 25 /*use enough decimal diigits for angles*/ call show 20, 45 /*display the angular difference (deg).*/ call show -45, 45 /* " " " " " */ call show -85, 90 /* " " " " " */ call show -95, 90 /* " " " " " */ call show -45, 125 /* " " " " " */ call show 45, 145 /* " " " " " */ call show 29.4803, -88.6361 /* " " " " " */ call show -78.3251, -159.036 /* " " " " " */ call show -70099.74233810938, 29840.67437876723 /* " " " " " */ call show -165313.6666297357, 33693.9894517456 /* " " " " " */ call show 1174.8380510598456,-154146.66490124757 /* " " " " " */ call show 60175.773067955546, 42213.07192354373 /* " " " " " */ exit /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ show: parse arg a,b; d=digits(); $='º' /*obtain the 2 angles (are in degrees).*/

     x=format( ( ( ((b-a) // 360) + 540) // 360) - 180, 4, d-4) /*compute and format.  */
     if pos(., x)\==0  then x=strip( strip(x, 'T', 0), "T", .)  /*strip trailing chaff.*/
     say center(a || $, d)      '─'      center(b || $, d)         "───►"         x || $
     return                                     /* [↑]  display the angular difference.*/</lang>

output

           20º            ─            45º            ───►   25º
          -45º            ─            45º            ───►   90º
          -85º            ─            90º            ───►  175º
          -95º            ─            90º            ───► -175º
          -45º            ─           125º            ───►  170º
           45º            ─           145º            ───►  100º
        29.4803º          ─         -88.6361º         ───► -118.1164º
        -78.3251º         ─         -159.036º         ───►  -80.7109º
   -70099.74233810938º    ─    29840.67437876723º     ───► -139.58328312339º
   -165313.6666297357º    ─     33693.9894517456º     ───►  -72.3439185187º
   1174.8380510598456º    ─   -154146.66490124757º    ───► -161.5029523074156º
   60175.773067955546º    ─    42213.07192354373º     ───►   37.298855588184º

Sidef

<lang ruby>func bearingAngleDiff(b1, b2) {

   (var b = ((b2 - b1 + 720) % 360)) > 180 ? (b - 360) : b

}

printf("%25s %25s %25s\n", "B1", "B2", "Difference") printf("%25s %25s %25s\n", "-"*20, "-"*20, "-"*20)


for b1,b2 in ([

                      20,                       45
                     -45,                       45
                     -85,                       90
                     -95,                       90
                     -45,                      125
                     -45,                      145
                 29.4803,                 -88.6381
                -78.3251,                 -159.036
      -70099.74233810938,        29840.67437876723
      -165313.6666297357,         33693.9894517456
      1174.8380510598456,      -154146.66490124757
       60175.77306795546,        42213.07192354373
   ].slices(2)

) {

   printf("%25s %25s %25s\n", b1, b2, bearingAngleDiff(b1, b2))

}</lang>

Output:
                       B1                        B2                Difference
     --------------------      --------------------      --------------------
                       20                        45                        25
                      -45                        45                        90
                      -85                        90                       175
                      -95                        90                      -175
                      -45                       125                       170
                      -45                       145                      -170
                  29.4803                  -88.6381                 -118.1184
                 -78.3251                  -159.036                  -80.7109
       -70099.74233810938         29840.67437876723          -139.58328312339
       -165313.6666297357          33693.9894517456            -72.3439185187
       1174.8380510598456       -154146.66490124757        -161.5029523074156
        60175.77306795546         42213.07192354373            37.29885558827

zkl

Translation of: Perl 6

<lang zkl>fcn bearingAngleDiff(b1,b2){ // -->Float, b1,b2 can be int or float

 ( (b:=(0.0 + b2 - b1 + 720)%360) > 180 ) and b - 360 or b;

}</lang> <lang zkl>T( 20,45, -45,45, -85,90, -95,90, -45,125, -45,145 ) .pump(Console.println,Void.Read,

     fcn(b1,b2){ "%.1f\UB0; + %.1f\UB0; = %.1f\UB0;"
                 .fmt(b1,b2,bearingAngleDiff(b1,b2)) });</lang>
Output:
20.0° + 45.0° = 25.0°
-45.0° + 45.0° = 90.0°
-85.0° + 90.0° = 175.0°
-95.0° + 90.0° = -175.0°
-45.0° + 125.0° = 170.0°
-45.0° + 145.0° = -170.0°

References