Averages/Mean angle: Difference between revisions

From Rosetta Code
Content added Content deleted
No edit summary
m (→‎{{header|Wren}}: Minor tidy)
 
(39 intermediate revisions by 28 users not shown)
Line 1: Line 1:
[[Category:Geometry]]
{{task}}
{{task}}


Line 19: Line 20:
::<math>\bar{\alpha} = \operatorname{atan2}\left(\frac{1}{n}\cdot\sum_{j=1}^n \sin\alpha_j, \frac{1}{n}\cdot\sum_{j=1}^n \cos\alpha_j\right) </math>
::<math>\bar{\alpha} = \operatorname{atan2}\left(\frac{1}{n}\cdot\sum_{j=1}^n \sin\alpha_j, \frac{1}{n}\cdot\sum_{j=1}^n \cos\alpha_j\right) </math>


;Task
{{task heading}}


# write a function/method/subroutine/... that given a list of angles in degrees returns their mean angle. <br> (You should use a built-in function if you have one that does this for degrees or radians).
# write a function/method/subroutine/... that given a list of angles in degrees returns their mean angle. <br> (You should use a built-in function if you have one that does this for degrees or radians).
Line 33: Line 34:


<br><hr>
<br><hr>

=={{header|11l}}==
{{trans|C#}}
<syntaxhighlight lang="11l">F mean_angle(angles)
V x = sum(angles.map(a -> cos(radians(a)))) / angles.len
V y = sum(angles.map(a -> sin(radians(a)))) / angles.len
R degrees(atan2(y, x))

print(mean_angle([350, 10]))
print(mean_angle([90, 180, 270, 360]))
print(mean_angle([10, 20, 30]))</syntaxhighlight>
{{out}}
<pre>
-1.61481e-15
-90
20
</pre>


=={{header|Ada}}==
=={{header|Ada}}==
An implementation based on the formula using the "Arctan" (atan2) function, thus avoiding complex numbers:
An implementation based on the formula using the "Arctan" (atan2) function, thus avoiding complex numbers:
<lang Ada>with Ada.Text_IO, Ada.Numerics.Generic_Elementary_Functions;
<syntaxhighlight lang="ada">with Ada.Text_IO, Ada.Numerics.Generic_Elementary_Functions;


procedure Mean_Angles is
procedure Mean_Angles is
Line 69: Line 87:
Put(Mean_Angle((10.0, 350.0))); Ada.Text_IO.New_Line; -- 0.00
Put(Mean_Angle((10.0, 350.0))); Ada.Text_IO.New_Line; -- 0.00
Put(Mean_Angle((90.0, 180.0, 270.0, 360.0))); -- Ada.Numerics.Argument_Error!
Put(Mean_Angle((90.0, 180.0, 270.0, 360.0))); -- Ada.Numerics.Argument_Error!
end Mean_Angles;</lang>
end Mean_Angles;</syntaxhighlight>
{{out}}
{{out}}
<pre> 20.00
<pre> 20.00
Line 75: Line 93:


raised ADA.NUMERICS.ARGUMENT_ERROR : a-ngelfu.adb:427 instantiated at mean_angles.adb:17</pre>
raised ADA.NUMERICS.ARGUMENT_ERROR : a-ngelfu.adb:427 instantiated at mean_angles.adb:17</pre>

=={{header|Aime}}==
<syntaxhighlight lang="aime">real
mean(list l)
{
integer i;
real x, y;

x = y = 0;

i = 0;
while (i < l_length(l)) {
x += Gcos(l[i]);
y += Gsin(l[i]);
i += 1;
}

return Gatan2(y / l_length(l), x / l_length(l));
}

integer
main(void)
{
o_form("mean of 1st set: /d6/\n", mean(l_effect(350, 10)));
o_form("mean of 2nd set: /d6/\n", mean(l_effect(90, 180, 270, 360)));
o_form("mean of 3rd set: /d6/\n", mean(l_effect(10, 20, 30)));

return 0;
}</syntaxhighlight>
{{out}}
<pre>mean of 1st set: -.000000
mean of 2nd set: -90
mean of 3rd set: 19.999999</pre>

=={{header|ALGOL 68}}==
=={{header|ALGOL 68}}==
{{works with|ALGOL 68|Revision 1}}
{{works with|ALGOL 68|Revision 1}}
Line 80: Line 132:
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d] - due to extensive use of '''format'''[ted] ''transput''.}}
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d] - due to extensive use of '''format'''[ted] ''transput''.}}
{{trans|C|Note: This specimen retains the original [[#C|C]] coding style}}
{{trans|C|Note: This specimen retains the original [[#C|C]] coding style}}
'''File: Averages_Mean_angle.a68'''<lang algol68>#!/usr/bin/a68g --script #
'''File: Averages_Mean_angle.a68'''<syntaxhighlight lang="algol68">#!/usr/bin/a68g --script #
# -*- coding: utf-8 -*- #
# -*- coding: utf-8 -*- #


Line 105: Line 157:
printf ((summary fmt,"2nd", mean angle (angle set 2)));
printf ((summary fmt,"2nd", mean angle (angle set 2)));
printf ((summary fmt,"3rd", mean angle (angle set 3)))
printf ((summary fmt,"3rd", mean angle (angle set 3)))
)</lang>{{out}}
)</syntaxhighlight>{{out}}
<pre>
<pre>
Mean angle for 1st set : -0.00000 degrees
Mean angle for 1st set : -0.00000 degrees
Line 111: Line 163:
Mean angle for 3rd set : 20.00000 degrees
Mean angle for 3rd set : 20.00000 degrees
</pre>
</pre>

=={{header|Aime}}==
<lang aime>real
mean(list l)
{
integer i;
real x, y;

x = y = 0;

i = 0;
while (i < l_length(l)) {
x += Gcos(l[i]);
y += Gsin(l[i]);
i += 1;
}

return Gatan2(y / l_length(l), x / l_length(l));
}

integer
main(void)
{
o_form("mean of 1st set: /d6/\n", mean(l_effect(350, 10)));
o_form("mean of 2nd set: /d6/\n", mean(l_effect(90, 180, 270, 360)));
o_form("mean of 3rd set: /d6/\n", mean(l_effect(10, 20, 30)));

return 0;
}</lang>
{{out}}
<pre>mean of 1st set: -.000000
mean of 2nd set: -90
mean of 3rd set: 19.999999</pre>


=={{header|AutoHotkey}}==
=={{header|AutoHotkey}}==
{{works with|AutoHotkey 1.1}}
{{works with|AutoHotkey 1.1}}
<lang AutoHotkey>Angles := [[350, 10], [90, 180, 270, 360], [10, 20, 30]]
<syntaxhighlight lang="autohotkey">Angles := [[350, 10], [90, 180, 270, 360], [10, 20, 30]]
MsgBox, % MeanAngle(Angles[1]) "`n"
MsgBox, % MeanAngle(Angles[1]) "`n"
. MeanAngle(Angles[2]) "`n"
. MeanAngle(Angles[2]) "`n"
Line 163: Line 182:
atan2(x, y) {
atan2(x, y) {
return dllcall("msvcrt\atan2", "Double",y, "Double",x, "CDECL Double")
return dllcall("msvcrt\atan2", "Double",y, "Double",x, "CDECL Double")
}</lang>
}</syntaxhighlight>
'''Output:'''
'''Output:'''
<pre>-0.000000
<pre>-0.000000
Line 170: Line 189:


=={{header|AWK}}==
=={{header|AWK}}==
<lang AWK>#!/usr/bin/awk -f
<syntaxhighlight lang="awk">#!/usr/bin/awk -f
{
{
PI = atan2(0,-1);
PI = atan2(0,-1);
Line 182: Line 201:
if (p<0) p += 360;
if (p<0) p += 360;
print p;
print p;
}</lang>
}</syntaxhighlight>
<pre> echo 350 10 | ./mean_angle.awk
<pre> echo 350 10 | ./mean_angle.awk
360
360
Line 192: Line 211:
=={{header|BBC BASIC}}==
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
{{works with|BBC BASIC for Windows}}
<lang bbcbasic> *FLOAT 64
<syntaxhighlight lang="bbcbasic"> *FLOAT 64
DIM angles(3)
DIM angles(3)
angles() = 350,10
angles() = 350,10
Line 211: Line 230:
DEF FNatan2(y,x) : ON ERROR LOCAL = SGN(y)*PI/2
DEF FNatan2(y,x) : ON ERROR LOCAL = SGN(y)*PI/2
IF x>0 THEN = ATN(y/x) ELSE IF y>0 THEN = ATN(y/x)+PI ELSE = ATN(y/x)-PI</lang>
IF x>0 THEN = ATN(y/x) ELSE IF y>0 THEN = ATN(y/x)+PI ELSE = ATN(y/x)-PI</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 217: Line 236:
-90
-90
20
20
</pre>

=={{header|Befunge}}==
<lang befunge>&:459**1-`#v_ >+\1+\~25*-#v_\/.>
>859**-^ > ^
</lang>
The code uses new lines to terminate a list. It does not work with numbers of degrees larger than 360.

Example input:
<pre>
350 10
10 20 30
90 180 270 360
</pre>
{{out}}
<pre>
0 20 -45
</pre>
</pre>


=={{header|C}}==
=={{header|C}}==
<lang c>#include<math.h>
<syntaxhighlight lang="c">#include<math.h>
#include<stdio.h>
#include<stdio.h>


Line 266: Line 268:
printf ("\nMean Angle for 3rd set : %lf degrees\n", meanAngle (angleSet3, 3));
printf ("\nMean Angle for 3rd set : %lf degrees\n", meanAngle (angleSet3, 3));
return 0;
return 0;
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>Mean Angle for 1st set : -0.000000 degrees
<pre>Mean Angle for 1st set : -0.000000 degrees
Line 273: Line 275:


=={{header|C sharp|C#}}==
=={{header|C sharp|C#}}==
<lang csharp>using System;
<syntaxhighlight lang="csharp">using System;
using System.Linq;
using System.Linq;
using static System.Math;
using static System.Math;
Line 291: Line 293:
printMean(new double[] { 10, 20, 30 });
printMean(new double[] { 10, 20, 30 });
}
}
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>0
<pre>0
-90
-90
20</pre>
20</pre>

=={{header|C++}}==
{{trans|C#}}
<syntaxhighlight lang="cpp">#include <iomanip>
#include <iostream>
#include <vector>

#define _USE_MATH_DEFINES
#include <math.h>

template<typename C>
double meanAngle(const C& c) {
auto it = std::cbegin(c);
auto end = std::cend(c);

double x = 0.0;
double y = 0.0;
double len = 0.0;
while (it != end) {
x += cos(*it * M_PI / 180);
y += sin(*it * M_PI / 180);
len++;

it = std::next(it);
}

return atan2(y, x) * 180 / M_PI;
}

void printMean(std::initializer_list<double> init) {
std::cout << std::fixed << std::setprecision(3) << meanAngle(init) << '\n';
}

int main() {
printMean({ 350, 10 });
printMean({ 90, 180, 270, 360 });
printMean({ 10, 20, 30 });

return 0;
}</syntaxhighlight>
{{out}}
<pre>-0.000
-90.000
20.000</pre>


=={{header|Clojure}}==
=={{header|Clojure}}==
<lang clojure>(defn mean-fn
<syntaxhighlight lang="clojure">(defn mean-fn
[k coll]
[k coll]
(let [n (count coll)
(let [n (count coll)
Line 309: Line 355:
a (mean-fn :sin radians)
a (mean-fn :sin radians)
b (mean-fn :cos radians)]
b (mean-fn :cos radians)]
(Math/toDegrees (Math/atan2 a b))))</lang>
(Math/toDegrees (Math/atan2 a b))))</syntaxhighlight>
Example:
Example:
<lang clojure>(mean-angle [350 10])
<syntaxhighlight lang="clojure">(mean-angle [350 10])
;=> -1.614809932057922E-15
;=> -1.614809932057922E-15


Line 318: Line 364:


(mean-angle [10 20 30])
(mean-angle [10 20 30])
;=> 19.999999999999996</lang>
;=> 19.999999999999996</syntaxhighlight>


=={{header|Common Lisp}}==
=={{header|Common Lisp}}==
<lang lisp>(defun average (list)
<syntaxhighlight lang="lisp">(defun average (list)
(/ (reduce #'+ list) (length list)))
(/ (reduce #'+ list) (length list)))


Line 328: Line 374:


(defun degrees (angle)
(defun degrees (angle)
(* 180 (/ 1 pi) angle))
(* (/ 180 pi) angle))


(defun mean-angle (angles)
(defun mean-angle (angles)
Line 337: Line 383:


(loop for angles in '((350 10) (90 180 270 360) (10 20 30))
(loop for angles in '((350 10) (90 180 270 360) (10 20 30))
do (format t "~&The mean angle of ~a is ~$°." angles (mean-angle angles)))</lang>
do (format t "~&The mean angle of ~a is ~$°." angles (mean-angle angles)))

;; or using complex numbers (cis and phase)

(defun mean-angle-2 (angles)
(degrees (phase (reduce #'+ angles :key (lambda (deg) (cis (radians deg)))))))
</syntaxhighlight>
{{out}}
{{out}}
<pre>The mean angle of (350 10) is -0.00°.
<pre>The mean angle of (350 10) is -0.00°.
Line 344: Line 396:


=={{header|D}}==
=={{header|D}}==
<lang d>import std.stdio, std.algorithm, std.complex;
<syntaxhighlight lang="d">import std.stdio, std.algorithm, std.complex;
import std.math: PI;
import std.math: PI;


Line 359: Line 411:
writefln("The mean angle of %s is: %.2f degrees",
writefln("The mean angle of %s is: %.2f degrees",
angles, angles.meanAngle);
angles, angles.meanAngle);
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>The mean angle of [350, 10] is: -0.00 degrees
<pre>The mean angle of [350, 10] is: -0.00 degrees
The mean angle of [90, 180, 270, 360] is: 90.00 degrees
The mean angle of [90, 180, 270, 360] is: 90.00 degrees
The mean angle of [10, 20, 30] is: 20.00 degrees</pre>
The mean angle of [10, 20, 30] is: 20.00 degrees</pre>
=={{header|Delphi}}==

See [[#Pascal]].
=={{header|EasyLang}}==
{{trans|C}}
<syntaxhighlight lang=easylang>
func mean ang[] .
for ang in ang[]
x += cos ang
y += sin ang
.
return atan2 (y / len ang[]) (x / len ang[])
.
print mean [ 350 10 ]
print mean [ 90 180 270 360 ]
print mean [ 10 20 30 ]
</syntaxhighlight>


=={{header|EchoLisp}}==
=={{header|EchoLisp}}==
<lang scheme>
<syntaxhighlight lang="scheme">
(define-syntax-rule (deg->radian deg) (* deg 1/180 PI))
(define-syntax-rule (deg->radian deg) (* deg 1/180 PI))
(define-syntax-rule (radian->deg rad) (* 180 (/ PI) rad))
(define-syntax-rule (radian->deg rad) (* 180 (/ PI) rad))
Line 382: Line 449:
(mean-angles '[10 20 30])
(mean-angles '[10 20 30])
→ 20
→ 20
</syntaxhighlight>
</lang>


=={{header|Elixir}}==
=={{header|Elixir}}==
<syntaxhighlight lang="elixir">
<lang Elixir>
defmodule MeanAngle do
defmodule MeanAngle do
def mean_angle(angles) do
def mean_angle(angles) do
Line 407: Line 474:
IO.inspect MeanAngle.mean_angle([90, 180, 270, 360])
IO.inspect MeanAngle.mean_angle([90, 180, 270, 360])
IO.inspect MeanAngle.mean_angle([10, 20, 30])
IO.inspect MeanAngle.mean_angle([10, 20, 30])
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 417: Line 484:
=={{header|Erlang}}==
=={{header|Erlang}}==
The function from_degrees/1 is used to solve [[Averages/Mean_time_of_day]]. Please keep backwards compatibility when editing. Or update the other module, too.
The function from_degrees/1 is used to solve [[Averages/Mean_time_of_day]]. Please keep backwards compatibility when editing. Or update the other module, too.
<syntaxhighlight lang="erlang">
<lang Erlang>
-module( mean_angle ).
-module( mean_angle ).
-export( [from_degrees/1, task/0] ).
-export( [from_degrees/1, task/0] ).
Line 437: Line 504:


radians( Degrees ) -> Degrees * math:pi() / 180.
radians( Degrees ) -> Degrees * math:pi() / 180.
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 447: Line 514:


=={{header|Euler Math Toolbox}}==
=={{header|Euler Math Toolbox}}==
<lang EulerMathToolbox>>function meanangle (a) ...
<syntaxhighlight lang="eulermathtoolbox">>function meanangle (a) ...
$ z=sum(exp(rad(a)*I));
$ z=sum(exp(rad(a)*I));
$ if z~=0 then error("Not meaningful");
$ if z~=0 then error("Not meaningful");
Line 462: Line 529:
if z~=0 then error("Not meaningful");
if z~=0 then error("Not meaningful");
>meanangle([10,20,30])
>meanangle([10,20,30])
20</lang>
20</syntaxhighlight>



=={{header|Euphoria}}==
=={{header|Euphoria}}==
{{works with|OpenEuphoria}}
{{works with|OpenEuphoria}}
<syntaxhighlight lang="euphoria">
<lang Euphoria>
include std/console.e
include std/console.e
include std/mathcons.e
include std/mathcons.e
Line 494: Line 560:


if getc(0) then end if
if getc(0) then end if
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 503: Line 569:


=={{header|F_Sharp|F#}}==
=={{header|F_Sharp|F#}}==
<lang fsharp>open System
<syntaxhighlight lang="fsharp">open System
open System.Numerics
open System.Numerics


Line 517: Line 583:
|> fun c -> c.Phase |> rad2deg
|> fun c -> c.Phase |> rad2deg
|> printfn "Mean angle for [%s]: %g°" (String.Join("; ",argv))
|> printfn "Mean angle for [%s]: %g°" (String.Join("; ",argv))
0</lang>
0</syntaxhighlight>
{{out}}
{{out}}
<pre>>RosettaCode 350 10
<pre>>RosettaCode 350 10
Line 527: Line 593:
>RosettaCode 90 180 270 360
>RosettaCode 90 180 270 360
Mean angle for [90; 180; 270; 360]: -90°
Mean angle for [90; 180; 270; 360]: -90°
</pre>

=={{header|Factor}}==
<syntaxhighlight lang="factor">USING: formatting kernel math math.functions math.libm math.trig
sequences ;

: mean-angle ( seq -- x )
[ deg>rad ] map [ [ sin ] map-sum ] [ [ cos ] map-sum ]
[ length ] tri recip [ * ] curry bi@ fatan2 rad>deg ;

: show ( seq -- )
dup mean-angle "The mean angle of %u is: %f°\n" printf ;

{ { 350 10 } { 90 180 270 360 } { 10 20 30 } } [ show ] each</syntaxhighlight>
{{out}}
<pre>
The mean angle of { 350 10 } is: -0.000000°
The mean angle of { 90 180 270 360 } is: -90.000000°
The mean angle of { 10 20 30 } is: 20.000000°
</pre>
</pre>


=={{header|Fortran}}==
=={{header|Fortran}}==
Please find the example output along with the build instructions in the comments at the start of the FORTRAN 2008 source. Compiler: gfortran from the GNU compiler collection. Command interpreter: bash.
Please find the example output along with the build instructions in the comments at the start of the FORTRAN 2008 source. Compiler: gfortran from the GNU compiler collection. Command interpreter: bash.
<syntaxhighlight lang="fortran">
<lang FORTRAN>
!-*- mode: compilation; default-directory: "/tmp/" -*-
!-*- mode: compilation; default-directory: "/tmp/" -*-
!Compilation started at Mon Jun 3 18:07:59
!Compilation started at Mon Jun 3 18:07:59
Line 568: Line 653:
end do
end do
end program average_angles
end program average_angles
</syntaxhighlight>
</lang>


=={{header|FreeBASIC}}==
=={{header|FreeBASIC}}==
<lang freebasic>
<syntaxhighlight lang="freebasic">
' FB 1.05.0 Win64
' FB 1.05.0 Win64


Line 597: Line 682:
Print "Press any key to quit the program"
Print "Press any key to quit the program"
Sleep
Sleep
</syntaxhighlight>
</lang>


{{out}}
{{out}}
Line 608: Line 693:
=={{header|Go}}==
=={{header|Go}}==
===Complex===
===Complex===
<lang go>package main
<syntaxhighlight lang="go">package main


import (
import (
Line 635: Line 720:
fmt.Printf("The mean angle of %v is: %f degrees\n", angles, mean_angle(angles))
fmt.Printf("The mean angle of %v is: %f degrees\n", angles, mean_angle(angles))
}
}
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 645: Line 730:
A mean_angle function that could be substituted above. Functions deg2rad and rad2deg are not used here but there is no runtime advantage either way to using them or not. Inlining should result in eqivalent code being generated. Also the Go Atan2 library function has no limits on the arguments so there is no need to divide by the number of elements.
A mean_angle function that could be substituted above. Functions deg2rad and rad2deg are not used here but there is no runtime advantage either way to using them or not. Inlining should result in eqivalent code being generated. Also the Go Atan2 library function has no limits on the arguments so there is no need to divide by the number of elements.


<lang go>func mean_angle(deg []float64) float64 {
<syntaxhighlight lang="go">func mean_angle(deg []float64) float64 {
var ss, sc float64
var ss, sc float64
for _, x := range deg {
for _, x := range deg {
Line 653: Line 738:
}
}
return math.Atan2(ss, sc) * 180 / math.Pi
return math.Atan2(ss, sc) * 180 / math.Pi
}</lang>
}</syntaxhighlight>


=={{header|Groovy}}==
=={{header|Groovy}}==
<lang groovy>import static java.lang.Math.*
<syntaxhighlight lang="groovy">import static java.lang.Math.*
def meanAngle = {
def meanAngle = {
atan2( it.sum { sin(it * PI / 180) } / it.size(), it.sum { cos(it * PI / 180) } / it.size()) * 180 / PI
atan2( it.sum { sin(it * PI / 180) } / it.size(), it.sum { cos(it * PI / 180) } / it.size()) * 180 / PI
}</lang>
}</syntaxhighlight>
Test:
Test:
<lang groovy>def verifyAngle = { angles ->
<syntaxhighlight lang="groovy">def verifyAngle = { angles ->
def ma = meanAngle(angles)
def ma = meanAngle(angles)
printf("Mean Angle for $angles: %5.2f%n", ma)
printf("Mean Angle for $angles: %5.2f%n", ma)
Line 668: Line 753:
assert verifyAngle([350, 10]) == -0
assert verifyAngle([350, 10]) == -0
assert verifyAngle([90, 180, 270, 360]) == -90
assert verifyAngle([90, 180, 270, 360]) == -90
assert verifyAngle([10, 20, 30]) == 20</lang>
assert verifyAngle([10, 20, 30]) == 20</syntaxhighlight>
{{out}}
{{out}}
<pre>Mean Angle for [350, 10]: -0.00
<pre>Mean Angle for [350, 10]: -0.00
Line 675: Line 760:


=={{header|Haskell}}==
=={{header|Haskell}}==
<lang haskell>import Data.Complex (cis, phase)
<syntaxhighlight lang="haskell">import Data.Complex (cis, phase)


meanAngle
meanAngle
Line 689: Line 774:
"The mean angle of " ++
"The mean angle of " ++
show angles ++ " is: " ++ show (meanAngle angles) ++ " degrees")
show angles ++ " is: " ++ show (meanAngle angles) ++ " degrees")
[[350, 10], [90, 180, 270, 360], [10, 20, 30]]</lang>
[[350, 10], [90, 180, 270, 360], [10, 20, 30]]</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 700: Line 785:
Alternative Solution: This solution gives an insight about using factoring, many small functions like Forth and using function composition.
Alternative Solution: This solution gives an insight about using factoring, many small functions like Forth and using function composition.


<lang haskell>
<syntaxhighlight lang="haskell">


-- file: trigdeg.fs
-- file: trigdeg.fs
Line 719: Line 804:


-- End of trigdeg.fs --------
-- End of trigdeg.fs --------
</syntaxhighlight>
</lang>


{{out}}
{{out}}
Line 742: Line 827:
=={{header|Icon}} and {{header|Unicon}}==
=={{header|Icon}} and {{header|Unicon}}==


<lang unicon>procedure main(A)
<syntaxhighlight lang="unicon">procedure main(A)
write("Mean angle is ",meanAngle(A))
write("Mean angle is ",meanAngle(A))
end
end
Line 750: Line 835:
every (sumCosines := 0.0) +:= cos(dtor(!A))
every (sumCosines := 0.0) +:= cos(dtor(!A))
return rtod(atan(sumSines/*A,sumCosines/*A))
return rtod(atan(sumSines/*A,sumCosines/*A))
end</lang>
end</syntaxhighlight>


Sample runs:
Sample runs:
Line 760: Line 845:
->ama 10 20 30
->ama 10 20 30
Mean angle is 20.0
Mean angle is 20.0
</pre>

=={{header|IDL}}==
<syntaxhighlight lang="idl">function mean_angle, phi
z = total(exp(complex(0,phi*!dtor)))
return, atan(imaginary(z),real_part(z))*!radeg
end</syntaxhighlight>

{{out}}
<pre>IDL> print, mean_angle([350, 10])
-7.80250e-06
IDL> print, mean_angle([90, 180, 270, 360])
90.0000
IDL> print, mean_angle([10, 20, 30])
20.0000
</pre>
</pre>


=={{header|J}}==
=={{header|J}}==
<lang J>avgAngleD=: 360|(_1 { [: (**|)&.+.@(+/ % #)&.(*.inv) 1,.])&.(1r180p1&*)</lang>
<syntaxhighlight lang="j">avgAngleD=: 360|(_1 { [: (**|)&.+.@(+/ % #)&.(*.inv) 1,.])&.(1r180p1&*)</syntaxhighlight>
This verb can be represented as simpler component verbs, for example:
This verb can be represented as simpler component verbs, for example:
<lang J>rfd=: 1r180p1&* NB. convert angle to radians from degrees
<syntaxhighlight lang="j">rfd=: 1r180p1&* NB. convert angle to radians from degrees
toComplex=: *.inv NB. maps integer pairs as length, complex angle (in radians)
toComplex=: *.inv NB. maps integer pairs as length, complex angle (in radians)
mean=: +/ % # NB. calculate arithmetic mean
mean=: +/ % # NB. calculate arithmetic mean
roundComplex=: (* * |)&.+. NB. discard an extraneous least significant bit of precision from a complex value whose magnitude is in the vicinity of 1
roundComplex=: (* * |)&.+. NB. discard an extraneous least significant bit of precision from a complex value whose magnitude is in the vicinity of 1
avgAngleR=: _1 { [: roundComplex@mean&.toComplex 1 ,. ] NB. calculate average angle in radians
avgAngleR=: _1 { [: roundComplex@mean&.toComplex 1 ,. ] NB. calculate average angle in radians
avgAngleD=: 360|avgAngleR&.rfd NB. calculate average angle in degrees</lang>
avgAngleD=: 360|avgAngleR&.rfd NB. calculate average angle in degrees</syntaxhighlight>
Example use:
Example use:
<lang J> avgAngleD 10 350
<syntaxhighlight lang="j"> avgAngleD 10 350
0
0
avgAngleD 90 180 270 360 NB. result not meaningful
avgAngleD 90 180 270 360 NB. result not meaningful
Line 781: Line 881:
5
5
avgAngleD 10 340
avgAngleD 10 340
355</lang>
355</syntaxhighlight>


Notes:
Notes:
Line 802: Line 902:
{{trans|NetRexx}}
{{trans|NetRexx}}
{{works with|Java|7+}}
{{works with|Java|7+}}
<lang java5>import java.util.Arrays;
<syntaxhighlight lang="java5">import java.util.Arrays;


public class AverageMeanAngle {
public class AverageMeanAngle {
Line 831: Line 931:
return Math.toDegrees(avgR);
return Math.toDegrees(avgR);
}
}
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>The mean angle of [350.0, 10.0] is -1.614809932057922E-15
<pre>The mean angle of [350.0, 10.0] is -1.614809932057922E-15
Line 841: Line 941:
=={{header|JavaScript}}==
=={{header|JavaScript}}==
===atan2===
===atan2===
<lang javascript>function sum(a) {
<syntaxhighlight lang="javascript">function sum(a) {
s = 0;
var s = 0;
for (var i in a) s += a[i];
for (var i = 0; i < a.length; i++) s += a[i];
return s;
return s;
}
}


function degToRad(a) {
function degToRad(a) {
return Math.PI/180*a;
return Math.PI / 180 * a;
}
}


function meanAngleDeg(a) {
function meanAngleDeg(a) {
return 180/Math.PI*Math.atan2(sum(a.map(degToRad).map(Math.sin))/a.length,sum(a.map(degToRad).map(Math.cos))/a.length);
return 180 / Math.PI * Math.atan2(
sum(a.map(degToRad).map(Math.sin)) / a.length,
sum(a.map(degToRad).map(Math.cos)) / a.length
);
}
}


var a = [350, 10], b = [90, 180, 270, 360], c =[10, 20, 30];
var a = [350, 10], b = [90, 180, 270, 360], c = [10, 20, 30];
console.log(meanAngleDeg(a));
console.log(meanAngleDeg(a));
console.log(meanAngleDeg(b));
console.log(meanAngleDeg(b));
console.log(meanAngleDeg(c));</lang>
console.log(meanAngleDeg(c));</syntaxhighlight>
{{out}}
{{out}}
<pre>-1.614809932057922e-15
<pre>-1.614809932057922e-15
Line 871: Line 974:


'''Generic Infrastructure'''
'''Generic Infrastructure'''
<lang jq>def pi: 4 * (1|atan);
<syntaxhighlight lang="jq">def pi: 4 * (1|atan);


def deg2rad: . * pi / 180;
def deg2rad: . * pi / 180;
Line 889: Line 992:
def abs: if . < 0 then - . else . end;
def abs: if . < 0 then - . else . end;
def summation(f): map(f) | add;</lang>
def summation(f): map(f) | add;</syntaxhighlight>


'''Mean Angle'''
'''Mean Angle'''
<lang jq># input: degrees
<syntaxhighlight lang="jq"># input: degrees
def mean_angle:
def mean_angle:
def round:
def round:
Line 906: Line 1,009:
| .[1]
| .[1]
| rad2deg
| rad2deg
| round;</lang>
| round;</syntaxhighlight>
'''Examples'''
'''Examples'''
<lang jq>([350, 10], [90, 180, 270, 360], [10, 20, 30])
<syntaxhighlight lang="jq">([350, 10], [90, 180, 270, 360], [10, 20, 30])
| "The mean angle of \(.) is: \(mean_angle)"</lang>
| "The mean angle of \(.) is: \(mean_angle)"</syntaxhighlight>


{{out}}
{{out}}
<lang sh>jq -r -n -f Mean_angle.jq
<syntaxhighlight lang="sh">jq -r -n -f Mean_angle.jq
The mean angle of [350,10] is: 0
The mean angle of [350,10] is: 0
The mean angle of [90,180,270,360] is: null
The mean angle of [90,180,270,360] is: null
The mean angle of [10,20,30] is: 20</lang>
The mean angle of [10,20,30] is: 20</syntaxhighlight>


=={{header|Julia}}==
=={{header|Julia}}==
Julia has built-in functions <code>sind</code> and <code>cosd</code> to compute the sine and cosine of angles specified in degrees accurately (avoiding the roundoff errors incurred in conversion to radians), and a built-in function to convert radians to degrees (or vice versa). Using these:
Julia has built-in functions <code>sind</code> and <code>cosd</code> to compute the sine and cosine of angles specified in degrees accurately (avoiding the roundoff errors incurred in conversion to radians), and a built-in function to convert radians to degrees (or vice versa). Using these:
<syntaxhighlight lang="julia">using Statistics
<lang julia>meandegrees(degrees) = radians2degrees(atan2(mean(sind(degrees)), mean(cosd(degrees))))</lang>
meandegrees(degrees) = rad2deg(atan(mean(sind.(degrees)), mean(cosd.(degrees))))</syntaxhighlight>
The output is:
The output is:
<lang julia>julia> meandegrees([350, 10])
<syntaxhighlight lang="julia">julia> meandegrees([350, 10])
0.0
0.0


Line 928: Line 1,032:


julia> meandegrees([10, 20, 30]])
julia> meandegrees([10, 20, 30]])
19.999999999999996</lang>
19.999999999999996</syntaxhighlight>
(Note that the mean of 90°, 180°, 270°, and 360° gives zero because of the lack of roundoff errors in the <code>sind</code> function, since the standard-library <code>atan2(0,0)</code> value is zero. Many of the other languages report an average of 90° or –90° in this case due to rounding errors.)
(Note that the mean of 90°, 180°, 270°, and 360° gives zero because of the lack of roundoff errors in the <code>sind</code> function, since the standard-library <code>atan2(0,0)</code> value is zero. Many of the other languages report an average of 90° or –90° in this case due to rounding errors.)


=={{header|Kotlin}}==
=={{header|Kotlin}}==
<lang scala>// version 1.0.5-2
<syntaxhighlight lang="scala">// version 1.0.5-2


fun meanAngle(angles: DoubleArray): Double {
fun meanAngle(angles: DoubleArray): Double {
Line 948: Line 1,052:
println("Mean for angles 2 is ${fmt.format(meanAngle(angles2))}")
println("Mean for angles 2 is ${fmt.format(meanAngle(angles2))}")
println("Mean for angles 3 is ${fmt.format(meanAngle(angles3))}")
println("Mean for angles 3 is ${fmt.format(meanAngle(angles3))}")
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 958: Line 1,062:


=={{header|Liberty BASIC}}==
=={{header|Liberty BASIC}}==
<lang lb>global Pi
<syntaxhighlight lang="lb">global Pi
Pi =3.1415926535
Pi =3.1415926535


Line 999: Line 1,103:
if y =0 and x =0 then notice "undefined": end
if y =0 and x =0 then notice "undefined": end
atan2 =at
atan2 =at
end function</lang>
end function</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 1,006: Line 1,110:
Mean Angle( "10,20,30") = 20.0 degrees.
Mean Angle( "10,20,30") = 20.0 degrees.
</pre>
</pre>

=={{header|Logo}}==
=={{header|Logo}}==
<lang logo>to mean_angle :angles
<syntaxhighlight lang="logo">to mean_angle :angles
local "avgsin
local "avgsin
make "avgsin quotient apply "sum map "sin :angles count :angles
make "avgsin quotient apply "sum map "sin :angles count :angles
Line 1,020: Line 1,125:


bye
bye
</syntaxhighlight>
</lang>


{{Out}}
{{Out}}
Line 1,030: Line 1,135:
{{trans|Tcl}}
{{trans|Tcl}}
{{works with|Lua|5.1}}
{{works with|Lua|5.1}}
<lang Lua>function meanAngle (angleList)
<syntaxhighlight lang="lua">function meanAngle (angleList)
local sumSin, sumCos = 0, 0
local sumSin, sumCos = 0, 0
for i, angle in pairs(angleList) do
for i, angle in pairs(angleList) do
Line 1,042: Line 1,147:
print(meanAngle({350, 10}))
print(meanAngle({350, 10}))
print(meanAngle({90, 180, 270, 360}))
print(meanAngle({90, 180, 270, 360}))
print(meanAngle({10, 20, 30}))</lang>
print(meanAngle({10, 20, 30}))</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 1,052: Line 1,157:
=={{header|Maple}}==
=={{header|Maple}}==
The following procedure takes a list of numeric degrees (with attached units) such as
The following procedure takes a list of numeric degrees (with attached units) such as
<lang Maple>> [ 350, 10 ] *~ Unit(arcdeg);
<syntaxhighlight lang="maple">> [ 350, 10 ] *~ Unit(arcdeg);
[350 [arcdeg], 10 [arcdeg]]</lang>
[350 [arcdeg], 10 [arcdeg]]</syntaxhighlight>
as input. (We could use "degree" instead of "arcdeg", since "degree" is taken, by default, to mean angle measure, but it seems best to avoid the ambiguity.)
as input. (We could use "degree" instead of "arcdeg", since "degree" is taken, by default, to mean angle measure, but it seems best to avoid the ambiguity.)
<lang Maple>MeanAngle := proc( L )
<syntaxhighlight lang="maple">MeanAngle := proc( L )
uses Units:-Standard; # for unit-awareness
uses Units:-Standard; # for unit-awareness
local u;
local u;
evalf( convert( argument( add( u, u = exp~( I *~ L ) ) ), 'units', 'radian', 'degree' ) )
evalf( convert( argument( add( u, u = exp~( I *~ L ) ) ), 'units', 'radian', 'degree' ) )
end proc:</lang>
end proc:</syntaxhighlight>
Applying this to the given data sets, we obtain:
Applying this to the given data sets, we obtain:
<lang Maple>> MeanAngle( [ 350, 10 ] *~ Unit(arcdeg) );
<syntaxhighlight lang="maple">> MeanAngle( [ 350, 10 ] *~ Unit(arcdeg) );
0.
0.


Line 1,068: Line 1,173:


> MeanAngle( [ 10, 20, 30 ] *~ Unit(arcdeg) );
> MeanAngle( [ 10, 20, 30 ] *~ Unit(arcdeg) );
20.00000000</lang>
20.00000000</syntaxhighlight>


=={{header|Mathematica}} / {{header|Wolfram Language}}==
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<lang Mathematica>meanAngle[data_List] := N@Arg[Mean[Exp[I data Degree]]]/Degree</lang>
<syntaxhighlight lang="mathematica">meanAngle[data_List] := N@Arg[Mean[Exp[I data Degree]]]/Degree</syntaxhighlight>
{{out}}
{{out}}
<pre>meanAngle /@ {{350, 10}, {90, 180, 270, 360}, {10, 20, 30}}
<pre>meanAngle /@ {{350, 10}, {90, 180, 270, 360}, {10, 20, 30}}
Line 1,077: Line 1,182:


=={{header|MATLAB}} / {{header|Octave}}==
=={{header|MATLAB}} / {{header|Octave}}==
<lang MATLAB>function u = mean_angle(phi)
<syntaxhighlight lang="matlab">function u = mean_angle(phi)
u = angle(mean(exp(i*pi*phi/180)))*180/pi;
u = angle(mean(exp(i*pi*phi/180)))*180/pi;
end</lang>
end</syntaxhighlight>
<pre> mean_angle([350, 10])
<pre> mean_angle([350, 10])
ans = -2.7452e-14
ans = -2.7452e-14
Line 1,086: Line 1,191:
mean_angle([10, 20, 30])
mean_angle([10, 20, 30])
ans = 20.000
ans = 20.000
</pre>

=={{header|MiniScript}}==
<syntaxhighlight lang="miniscript">
atan2 = function(y, x)
return 2 * atan((sqrt(x^2 + y^2) - x) / y)
end function

deg2rad = function(x); return x * pi / 180; end function
rad2deg = function(x); return x * 180 / pi; end function

meanAngle = function(angles)
xsum = 0; ysum = 0
for angle in angles
xsum += cos(deg2rad(angle))
ysum += sin(deg2rad(angle))
end for
return rad2deg(atan2(ysum / angles.len, xsum / angles.len))
end function

manyAngledOnes = [[350, 10], [90, 180, 270, 360], [10, 20, 30]]

for angles in manyAngledOnes
mean = meanAngle(angles)
print ["Mean of", angles, "is", mean].join(" ")
end for
</syntaxhighlight>
{{out}}
<pre>
Mean of [350, 10] is 0
Mean of [90, 180, 270, 360] is -90
Mean of [10, 20, 30] is 20.0
</pre>
</pre>


=={{header|NetRexx}}==
=={{header|NetRexx}}==
{{trans|C}}
{{trans|C}}
<lang NetRexx>/* NetRexx */
<syntaxhighlight lang="netrexx">/* NetRexx */
options replace format comments java crossref symbols nobinary
options replace format comments java crossref symbols nobinary
numeric digits 80
numeric digits 80
Line 1,123: Line 1,260:
end angles
end angles
return
return
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 1,143: Line 1,280:


=={{header|Nim}}==
=={{header|Nim}}==
{{works with|Nim|0.20.0+}}
<lang nim>import math, complex
<syntaxhighlight lang="nim">import math, complex
proc rect(r, phi: float): Complex = (r * cos(phi), sin(phi))
proc phase(c: Complex): float = arctan2(c.im, c.re)
proc radians(x: float): float = (x * Pi) / 180.0
proc degrees(x: float): float = (x * 180.0) / Pi
proc meanAngle(deg: openArray[float]): float =
proc meanAngle(deg: openArray[float]): float =
var c: Complex
var c: Complex[float]
for d in deg:
for d in deg:
c += rect(1.0, radians(d))
c += rect(1.0, degToRad(d))
degrees(phase(c / float(deg.len)))
radToDeg(phase(c / float(deg.len)))
echo "The 1st mean angle is: ", meanAngle([350.0, 10.0]), " degrees"
echo "The 1st mean angle is: ", meanAngle([350.0, 10.0]), " degrees"
echo "The 2nd mean angle is: ", meanAngle([90.0, 180.0, 270.0, 360.0]), " degrees"
echo "The 2nd mean angle is: ", meanAngle([90.0, 180.0, 270.0, 360.0]), " degrees"
echo "The 3rd mean angle is: ", meanAngle([10.0, 20.0, 30.0]), " degrees"</lang>
echo "The 3rd mean angle is: ", meanAngle([10.0, 20.0, 30.0]), " degrees"</syntaxhighlight>
Output:
Output:
<pre>The 1st mean angle is: -2.745176884498468e-14 degrees
<pre>The 1st mean angle is: -1.614809932057922e-15 degrees
The 2nd mean angle is: -90.0 degrees
The 2nd mean angle is: -90.0 degrees
The 3rd mean angle is: 20.0 degrees</pre>
The 3rd mean angle is: 20.0 degrees</pre>
Line 1,167: Line 1,299:
=={{header|Oberon-2}}==
=={{header|Oberon-2}}==
{{works with|oo2c}}
{{works with|oo2c}}
<lang oberon2>
<syntaxhighlight lang="oberon2">
MODULE MeanAngle;
MODULE MeanAngle;
IMPORT
IMPORT
Line 1,200: Line 1,332:
Out.LongRealFix(Mean(grades) * toDegs,15,9);Out.Ln;
Out.LongRealFix(Mean(grades) * toDegs,15,9);Out.Ln;
END MeanAngle.
END MeanAngle.
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 1,209: Line 1,341:


=={{header|OCaml}}==
=={{header|OCaml}}==
<lang ocaml>let pi = 3.14159_26535_89793_23846_2643
<syntaxhighlight lang="ocaml">let pi = 3.14159_26535_89793_23846_2643


let deg2rad d =
let deg2rad d =
Line 1,233: Line 1,365:
test [90.0; 180.0; 270.0; 360.0];
test [90.0; 180.0; 270.0; 360.0];
test [10.0; 20.0; 30.0];
test [10.0; 20.0; 30.0];
;;</lang>
;;</syntaxhighlight>
or using the <code>Complex</code> module:
or using the <code>Complex</code> module:
<lang ocaml>open Complex
<syntaxhighlight lang="ocaml">open Complex


let mean_angle angles =
let mean_angle angles =
Line 1,241: Line 1,373:
List.fold_left (fun sum a -> add sum (polar 1.0 (deg2rad a))) zero angles
List.fold_left (fun sum a -> add sum (polar 1.0 (deg2rad a))) zero angles
in
in
rad2deg (arg sum)</lang>
rad2deg (arg sum)</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 1,251: Line 1,383:
=={{header|ooRexx}}==
=={{header|ooRexx}}==
{{trans|REXX}}
{{trans|REXX}}
<lang oorexx>/*REXX program computes the mean angle (angles expressed in degrees). */
<syntaxhighlight lang="oorexx">/*REXX program computes the mean angle (angles expressed in degrees). */
numeric digits 50 /*use fifty digits of precision, */
numeric digits 50 /*use fifty digits of precision, */
showDig=10 /*··· but only display 10 digits.*/
showDig=10 /*··· but only display 10 digits.*/
Line 1,274: Line 1,406:
return left('angles='a,30) 'mean angle=' format(mA,,showDig,0)/1
return left('angles='a,30) 'mean angle=' format(mA,,showDig,0)/1


::requires rxMath library;</lang>
::requires rxMath library;</syntaxhighlight>
{{out}}
{{out}}
<pre>angles=350 10 mean angle= 0
<pre>angles=350 10 mean angle= 0
angles=90 180 270 360 mean angle= 0
angles=90 180 270 360 mean angle= 0
angles=10 20 30 mean angle= 20</pre>
angles=10 20 30 mean angle= 20</pre>

=={{header|PARI/GP}}==
=={{header|PARI/GP}}==
<lang parigp>meanAngle(v)=atan(sum(i=1,#v,sin(v[i]))/sum(i=1,#v,cos(v[i])))%(2*Pi)
<syntaxhighlight lang="parigp">meanAngle(v)=atan(sum(i=1,#v,sin(v[i]))/sum(i=1,#v,cos(v[i])))%(2*Pi)
meanDegrees(v)=meanAngle(v*Pi/180)*180/Pi
meanDegrees(v)=meanAngle(v*Pi/180)*180/Pi
apply(meanDegrees,[[350, 10], [90, 180, 270, 360], [10, 20, 30]])</lang>
apply(meanDegrees,[[350, 10], [90, 180, 270, 360], [10, 20, 30]])</syntaxhighlight>
{{out}}
{{out}}
<pre>[360.000000, 296.565051, 20.0000000]</pre>
<pre>[360.000000, 296.565051, 20.0000000]</pre>

=={{header|Pascal}}==
=={{header|Pascal}}==
uses library math for sincos, a function of FPU80x87, atan2 and DegToRad.
uses library math for sincos, a function of FPU80x87, atan2 and DegToRad.
Tested with free pascal.
Tested with free pascal.
Try to catch very small cos values and set to 0.0 degrees " Error : Not meaningful" as http://rosettacode.org/wiki/Averages/Mean_angle#Euler_Math_Toolbox complains.
Try to catch very small cos values and set to 0.0 degrees " Error : Not meaningful" as http://rosettacode.org/wiki/Averages/Mean_angle#Euler_Math_Toolbox complains.
<lang pascal>program MeanAngle;
<syntaxhighlight lang="pascal">program MeanAngle;
{$IFDEF DELPHI}
{$IFDEF DELPHI}
{$APPTYPE CONSOLE}
{$APPTYPE CONSOLE}
Line 1,360: Line 1,493:


setlength(a,0);
setlength(a,0);
end.</lang>
end.</syntaxhighlight>
;output:
;output:
<pre>
<pre>
Line 1,368: Line 1,501:


=={{header|Perl}}==
=={{header|Perl}}==
<lang perl>sub Pi () { 3.1415926535897932384626433832795028842 }
<syntaxhighlight lang="perl">sub Pi () { 3.1415926535897932384626433832795028842 }


sub meanangle {
sub meanangle {
Line 1,384: Line 1,517:


print "The mean angle of [@$_] is: ", meandegrees(@$_), " degrees\n"
print "The mean angle of [@$_] is: ", meandegrees(@$_), " degrees\n"
for ([350,10], [90,180,270,360], [10,20,30]);</lang>
for ([350,10], [90,180,270,360], [10,20,30]);</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 1,391: Line 1,524:
The mean angle of [10 20 30] is: 20 degrees
The mean angle of [10 20 30] is: 20 degrees
</pre>
</pre>

=={{header|Perl 6}}==
{{works with|Rakudo|2015.12}}
This solution refuses to return an answer when the angles cancel out to a tiny magnitude.
<lang perl6># Of course, you can still use pi and 180.
sub deg2rad { $^d * tau / 360 }
sub rad2deg { $^r * 360 / tau }

sub phase ($c) {
my ($mag,$ang) = $c.polar;
return NaN if $mag < 1e-16;
$ang;
}

sub meanAngle { rad2deg phase [+] map { cis deg2rad $_ }, @^angles }

say meanAngle($_).fmt("%.2f\tis the mean angle of "), $_ for
[350, 10],
[90, 180, 270, 360],
[10, 20, 30];</lang>
{{out}}
<pre>-0.00 is the mean angle of 350 10
NaN is the mean angle of 90 180 270 360
20.00 is the mean angle of 10 20 30</pre>


=={{header|Phix}}==
=={{header|Phix}}==
Copied from [[Euphoria]], and slightly improved
Copied from [[Averages/Mean_angle#Euphoria|Euphoria]], and slightly improved
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>function atan2(atom y, atom x)
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
return 2*arctan((sqrt(power(x,2)+power(y,2))-x)/y)
<span style="color: #008080;">function</span> <span style="color: #000000;">MeanAngle</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">angles</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #004080;">atom</span> <span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>

<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">angles</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
function MeanAngle(sequence angles)
<span style="color: #004080;">atom</span> <span style="color: #000000;">ai_rad</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">angles</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]*</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">/</span><span style="color: #000000;">180</span>
atom x=0, y=0, ai_rad
<span style="color: #000000;">x</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">cos</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ai_rad</span><span style="color: #0000FF;">)</span>
integer l=length(angles)
<span style="color: #000000;">y</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ai_rad</span><span style="color: #0000FF;">)</span>

<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
for i=1 to l do
<span style="color: #008080;">if</span> <span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)<</span><span style="color: #000000;">1e-16</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #008000;">"not meaningful"</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
ai_rad = angles[i]*PI/180
<span style="color: #008080;">return</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%g"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">round</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">atan2</span><span style="color: #0000FF;">(</span><span style="color: #000000;">y</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</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: #0000FF;">,</span><span style="color: #000000;">1e10</span><span style="color: #0000FF;">))</span>
x += cos(ai_rad)
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
y += sin(ai_rad)
end for
<span style="color: #008080;">constant</span> <span style="color: #000000;">AngleLists</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">350</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">180</span><span style="color: #0000FF;">,</span><span style="color: #000000;">270</span><span style="color: #0000FF;">,</span><span style="color: #000000;">360</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">20</span><span style="color: #0000FF;">,</span><span style="color: #000000;">30</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">180</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">180</span><span style="color: #0000FF;">}}</span>
if abs(x)<1e-16 then return "not meaningful" end if
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">AngleLists</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
return sprintf("%9.5f",atan2(y,x)*180/PI)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">ai</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">AngleLists</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
end function
<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;">"%16V: Mean Angle is %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">ai</span><span style="color: #0000FF;">,</span><span style="color: #000000;">MeanAngle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ai</span><span style="color: #0000FF;">)})</span>

<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
constant AngleLists = {{350,10},{90,180,270,360},{10,20,30},{180},{0,180}}
<!--</syntaxhighlight>-->
sequence ai
for i=1 to length(AngleLists) do
ai = AngleLists[i]
printf(1,"%+16s: Mean Angle is %s\n",{sprint(ai),MeanAngle(ai)})
end for
{} = wait_key()</lang>
{{out}}
{{out}}
<pre>
<pre>
{350,10}: Mean Angle is 0.00000
{350,10}: Mean Angle is 0
{90,180,270,360}: Mean Angle is not meaningful
{90,180,270,360}: Mean Angle is not meaningful
{10,20,30}: Mean Angle is 20.00000
{10,20,30}: Mean Angle is 20
{180}: Mean Angle is 180.00000
{180}: Mean Angle is 180
{0,180}: Mean Angle is not meaningful
{0,180}: Mean Angle is not meaningful
</pre>
</pre>
Line 1,453: Line 1,557:
=={{header|PHP}}==
=={{header|PHP}}==
{{trans|C}}
{{trans|C}}
<lang php><?php
<syntaxhighlight lang="php"><?php
$samples = array(
$samples = array(
'1st' => array(350, 10),
'1st' => array(350, 10),
Line 1,475: Line 1,579:
return rad2deg(atan2($y_part, $x_part));
return rad2deg(atan2($y_part, $x_part));
}
}
?></lang>
?></syntaxhighlight>
{{out}}
{{out}}
<pre>Mean angle for 1st sample: -1.6148099320579E-15 degrees.
<pre>Mean angle for 1st sample: -1.6148099320579E-15 degrees.
Line 1,482: Line 1,586:


=={{header|PicoLisp}}==
=={{header|PicoLisp}}==
<lang PicoLisp>(load "@lib/math.l")
<syntaxhighlight lang="picolisp">(load "@lib/math.l")


(de meanAngle (Lst)
(de meanAngle (Lst)
Line 1,495: Line 1,599:
"The mean angle of ["
"The mean angle of ["
(glue ", " (mapcar round L '(0 .)))
(glue ", " (mapcar round L '(0 .)))
"] is: " (round (meanAngle L))) )</lang>
"] is: " (round (meanAngle L))) )</syntaxhighlight>
{{out}}
{{out}}
<pre>The mean angle of [350, 10] is: 0.000
<pre>The mean angle of [350, 10] is: 0.000
Line 1,502: Line 1,606:


=={{header|PL/I}}==
=={{header|PL/I}}==
<lang PL/I>averages: procedure options (main); /* 31 August 2012 */
<syntaxhighlight lang="pl/i">averages: procedure options (main); /* 31 August 2012 */
declare b1(2) fixed initial (350, 10);
declare b1(2) fixed initial (350, 10);
declare b2(4) fixed initial (90, 180, 270, 360);
declare b2(4) fixed initial (90, 180, 270, 360);
Line 1,519: Line 1,623:
end mean;
end mean;


end averages;</lang>
end averages;</syntaxhighlight>
Results (the final one brings up an error in inverse tangent):
Results (the final one brings up an error in inverse tangent):
<pre>
<pre>
Line 1,530: Line 1,634:


=={{header|PowerShell}}==
=={{header|PowerShell}}==
<syntaxhighlight lang="powershell">
<lang PowerShell>
function Get-MeanAngle ([double[]]$Angles)
function Get-MeanAngle ([double[]]$Angles)
{
{
Line 1,538: Line 1,642:
[Math]::Atan2($y, $x) * 180 / [Math]::PI
[Math]::Atan2($y, $x) * 180 / [Math]::PI
}
}
</syntaxhighlight>
</lang>


<syntaxhighlight lang="powershell">
<lang PowerShell>
@(350, 10), @(90, 180, 270, 360), @(10, 20, 30) | ForEach-Object {Get-MeanAngle $_}
@(350, 10), @(90, 180, 270, 360), @(10, 20, 30) | ForEach-Object {Get-MeanAngle $_}
</syntaxhighlight>
</lang>


{{Out}}
{{Out}}
Line 1,550: Line 1,654:
20
20
</pre>
</pre>

=={{header|Processing}}==
<syntaxhighlight lang="processing">void setup() {
println(meanAngle(350, 10));
println(meanAngle(90, 180, 270, 360));
println(meanAngle(10, 20, 30));
}

float meanAngle(float... angles) {
float sum1 = 0, sum2 = 0;
for (int i = 0; i < angles.length; i++) {
sum1 += sin(radians(angles[i])) / angles.length;
sum2 += cos(radians(angles[i])) / angles.length;
}
return degrees(atan2(sum1, sum2));
}</syntaxhighlight>
{{out}}
<pre>-7.8025005E-6
90.0
20.0</pre>

=={{header|PureBasic}}==
<syntaxhighlight lang="purebasic">NewList angle.d()

Macro AE(x)
AddElement(angle()) : angle()=x
EndMacro

Procedure.d atan3(y.d,x.d)
If x<=0.0 : ProcedureReturn Sign(y)*#PI/2 : EndIf
If x>0.0 : ProcedureReturn ATan(y/x) : EndIf
If y>0.0 : ProcedureReturn ATan(y/x)+#PI : EndIf
ProcedureReturn ATan(y/x)-#PI
EndProcedure

Procedure.d mAngle(List angle.d())
Define.d sumS,sumC
ForEach angle()
sumS+Sin(Radian(angle())) : sumC+Cos(Radian(angle()))
Next
ProcedureReturn Degree(atan3(sumS,sumC))
EndProcedure

AE(350.0) : AE(10.0)
Debug StrD(mAngle(angle()),6) : ClearList(angle())

AE(90.0) : AE(180.0) : AE(270.0) : AE(360.0)
Debug StrD(mAngle(angle()),6) : ClearList(angle())

AE(10.0) : AE(20.0) : AE(30.0)
Debug StrD(mAngle(angle()),6) : ClearList(angle())
</syntaxhighlight>
{{out}}
<pre>-0.000000
-90.000000
20.000000</pre>


=={{header|Python}}==
=={{header|Python}}==
{{works with|Python|2.6+}}
{{works with|Python|2.6+}}
<lang python>>>> from cmath import rect, phase
<syntaxhighlight lang="python">>>> from cmath import rect, phase
>>> from math import radians, degrees
>>> from math import radians, degrees
>>> def mean_angle(deg):
>>> def mean_angle(deg):
Line 1,564: Line 1,724:
The mean angle of [90, 180, 270, 360] is: -90.0 degrees
The mean angle of [90, 180, 270, 360] is: -90.0 degrees
The mean angle of [10, 20, 30] is: 20.0 degrees
The mean angle of [10, 20, 30] is: 20.0 degrees
>>> </lang>
>>> </syntaxhighlight>

=={{header|R}}==
<syntaxhighlight lang="r">
deg2rad <- function(x) {
x * pi/180
}

rad2deg <- function(x) {
x * 180/pi
}

deg2vec <- function(x) {
c(sin(deg2rad(x)), cos(deg2rad(x)))
}

vec2deg <- function(x) {
res <- rad2deg(atan2(x[1], x[2]))
if (res < 0) {
360 + res
} else {
res
}
}

mean_vec <- function(x) {
y <- lapply(x, deg2vec)
Reduce(`+`, y)/length(y)
}

mean_deg <- function(x) {
vec2deg(mean_vec(x))
}

mean_deg(c(350, 10))
mean_deg(c(90, 180, 270, 360))
mean_deg(c(10, 20, 30))
</syntaxhighlight>
{{out}}
<pre>
360
270
20
</pre>


=={{header|Racket}}==
=={{header|Racket}}==
The formula given above can be straightforwardly transcribed into a program:
The formula given above can be straightforwardly transcribed into a program:
<lang racket>
<syntaxhighlight lang="racket">
#lang racket
#lang racket


Line 1,584: Line 1,787:
(mean-angle '(90 180 270 360))
(mean-angle '(90 180 270 360))
(mean-angle '(10 20 30))
(mean-angle '(10 20 30))
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 1,591: Line 1,794:
19.999999999999996
19.999999999999996
</pre>
</pre>

=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2015.12}}
This solution refuses to return an answer when the angles cancel out to a tiny magnitude.
<syntaxhighlight lang="raku" line># Of course, you can still use pi and 180.
sub deg2rad { $^d * tau / 360 }
sub rad2deg { $^r * 360 / tau }

sub phase ($c) {
my ($mag,$ang) = $c.polar;
return NaN if $mag < 1e-16;
$ang;
}

sub meanAngle { rad2deg phase [+] map { cis deg2rad $_ }, @^angles }

say meanAngle($_).fmt("%.2f\tis the mean angle of "), $_ for
[350, 10],
[90, 180, 270, 360],
[10, 20, 30];</syntaxhighlight>
{{out}}
<pre>-0.00 is the mean angle of 350 10
NaN is the mean angle of 90 180 270 360
20.00 is the mean angle of 10 20 30</pre>


=={{header|REXX}}==
=={{header|REXX}}==
This REXX version uses an &nbsp; '''ATAN2''' &nbsp; solution.
This REXX version uses an &nbsp; '''ATAN2''' &nbsp; solution.


The REXX language doesn't have most of the higher mathematical functions (like '''sqrt'''), and
The REXX language doesn't have most of the higher mathematical functions
(like '''sqrt'''), and
none of the trigonometric functions, so all of them have to be included as RYO &nbsp; ('''R'''oll-'''Y'''our-'''O'''wn).
none of the trigonometric
<br>functions, &nbsp; so all of them have to be included as
RYO &nbsp; ('''R'''oll-'''Y'''our-'''O'''wn).
<pre>
<pre>
Note that the second set of angles: 90 180 270 360
Note that the second set of angles: 90 180 270 360

is the same as: 90 180 -90 0
is the same as: 90 180 -90 0
and: -270 -180 -90 -360
and: -270 -180 -90 -360
Line 1,605: Line 1,836:
and other combinations.
and other combinations.
</pre>
</pre>
All the trigonometric functions use normalization &nbsp; (converting the
All the trigonometric functions use normalization &nbsp; (converting the angle to a unit circle) &nbsp; before computation, and most of them use shortcuts for some exact values, so there is a minimum of errors due to rounding for &nbsp; ''near values'' &nbsp; for some common values. &nbsp; The consequence is the trigonometric functions may return exact values such as &nbsp; '''0''' &nbsp; (zero) &nbsp; for &nbsp; '''sin(-2π)''' &nbsp; instead of &nbsp; '''-8.154E-61'''.
angle to a unit circle) &nbsp; before computation, &nbsp; and most
<br>of them use shortcuts for some exact values, &nbsp; so there is a minimum of
errors due to rounding for &nbsp; ''near values'' &nbsp; for some
<br>common values.


The consequence is the trig functions may return exact values such
This very small difference (almost inconsequential) makes a significant difference when that value is used for a parameter for the &nbsp; '''ATAN2''' &nbsp; function; &nbsp; in particular, the sign of the value. &nbsp;
as &nbsp; '''0''' &nbsp; (zero) &nbsp; for &nbsp; '''sin(-2<big><big><math>\pi</math></big></big>)''' &nbsp; instead
of &nbsp; '''-8.154E-61'''.


This very small difference (almost inconsequential) makes a significant difference
There isn't much difference between:
when that value is used for a parameter
<pre>
<br>for the &nbsp; '''ATAN2''' &nbsp; function; &nbsp; in
particular, the &nbsp; ''sign'' &nbsp; of the value.

There isn't much difference between:
-8.154e-61 and
-8.154e-61 and
+8.154e-61
+8.154e-61
in magnitude, but the &nbsp; '''ATAN2''' &nbsp; function treats those two numbers
</pre>
in magnitude, but the '''ATAN2''' function treats those two numbers very differently as the angle is in different quadrants, thereby yielding a different value.
very differently as the angle will be in different quadrants,
<br>thereby yielding a different value.

Usually this just results in an angle of &nbsp; '''-90º''' &nbsp; instead
of &nbsp; '''+270º''' &nbsp; (both angles are equivalent).


Also note that the REXX subroutines are largely not commented as they provide a
Usually this just results in an angle of &nbsp; '''-90º''' &nbsp; instead of &nbsp; '''+270º''' &nbsp; (both angles are equivalent).
support structure that's normally present
<br><br>Also note that the REXX subroutines are largely not commented as they provide a support structure that's normally present in other languages as BIFs &nbsp; ('''B'''uilt-'''I'''n-'''F'''unctions); &nbsp; to add comments and expand the REXX statements into single lines would detract from the main program.
<br>in other computer programming languages as
<lang rexx>/*REXX program computes the mean angle for a group of angles (expressed in degrees). */
BIFs &nbsp; ('''B'''uilt-'''I'''n-'''F'''unctions); &nbsp; to add comments and expand the
REXX statements
<br>into single lines would increase the program's bulk and detract from the main program.
<syntaxhighlight lang="rexx">/*REXX program computes the mean angle for a group of angles (expressed in degrees). */
call pi /*define the value of pi to some accuracy.*/
call pi /*define the value of pi to some accuracy.*/
numeric digits length(pi) - 1; showDig=10 /*use PI width decimal digits of precision,*/
numeric digits length(pi) - 1; /*use PI width decimal digits of precision,*/
/* but only display 10 decimal digits. */
showDig= 10 /*only display ten decimal digits. */
#=350 10 ; say show(#, meanAngleD(#) )
#= 350 10 ; say show(#, meanAngleD(#)) /*display mean angle (in degrees), 1st case.*/
#=90 180 270 360 ; say show(#, meanAngleD(#) )
#= 90 180 270 360 ; say show(#, meanAngleD(#)) /* " " " " " 2nd " */
#=10 20 30 ; say show(#, meanAngleD(#) )
#= 10 20 30 ; say show(#, meanAngleD(#)) /* " " " " " 3rd " */
exit /*stick a fork in it, we're all done with it*/
exit /*stick a fork in it, we're all done with it*/
/*───────────────────────────────────────────────────────────────────────────────────────────*/
/*───────────────────────────────────────────────────────────────────────────────────────────*/
Line 1,635: Line 1,884:
r2d: return d2d((r2r(arg(1)) / pi()) * 180)
r2d: return d2d((r2r(arg(1)) / pi()) * 180)
r2r: return arg(1) // (pi() * 2)
r2r: return arg(1) // (pi() * 2)
p: return word(arg(1), 1)
pi: pi=3.1415926535897932384626433832795028841971693993751058209749445923078164062862;return pi
pi: pi=3.1415926535897932384626433832795028841971693993751058209749445923078164062862;return pi
/*───────────────────────────────────────────────────────────────────────────────────────────*/

Asin: procedure; parse arg x 1 z 1 o 1 p; xx=x*x
Asin: procedure; parse arg x 1 z 1 o 1 p; a= abs(x); aa= a * a
if xx>=.5 then return sign(x) * Acos(sqrt(1-xx))
if a>1 then call AsinErr x /*argument X is out of range.*/
do j=2 by 2 until p=z; p=z; o=o*xx*(j-1)/j; z=z+o/(j+1); end /*j*/
if a >= sqrt(2) * .5 then return sign(x) * acos( sqrt(1 - aa), '-ASIN')
return z /* [↑] compute until no more noise.*/
do j=2 by 2 until p=z; p= z; o= o * aa * (j-1) / j; z= z +o / (j+1); end
return z /* [↑] compute until no noise*/

/*───────────────────────────────────────────────────────────────────────────────────────────*/
Atan2: procedure; parse arg y,x; call pi; s=sign(y)
Atan2: procedure; parse arg y,x; call pi; s= sign(y)
select
select
when x=0 then z=s * pi * .5
when x=0 then z= s * pi * .5
when x<0 then if y=0 then z=pi; else z=s * (pi - abs( Atan(y/x) ) )
when x<0 then if y=0 then z= pi; else z= s * (pi - abs( Atan(y/x) ) )
otherwise z=s * Atan(y/x)
otherwise z= s * Atan(y / x)
end /*select*/; return z
end /*select*/; return z
/*───────────────────────────────────────────────────────────────────────────────────────────*/

cos: procedure; parse arg x; x=r2r(x); numeric fuzz $fuzz(6, 3)
cos: procedure; parse arg x; x= r2r(x); numeric fuzz $fuzz(6, 3)
a=abs(x); if a=0 then return 1; if a=pi then return -1
a= abs(x); if a=0 then return 1; if a=pi then return -1
if a=pi*.5 | a=pi*1.5 then return 0; if a=pi/3 then return .5
if a=pi*.5 | a= pi*1.5 then return 0; if a=pi/3 then return .5
if a=pi*2/3 then return -.5; return .sinCos(1, 1, -1)
if a= pi*2/3 then return -.5; return .sinCos(1, 1, -1)
/*───────────────────────────────────────────────────────────────────────────────────────────*/

meanAngleD: procedure; parse arg x; numeric digits digits()+digits()%4
meanAngleD: procedure; parse arg x; numeric digits digits() + digits() % 4
n=words(x); _sin=0; _cos=0
n= words(x); _sin= 0; _cos= 0
do j=1 for n; !=d2r(word(x, j)); _sin=_sin+sin(!); _cos=_cos+cos(!); end /*j*/
do j=1 for n; != d2r( word(x, j)); _sin= _sin + sin(!); _cos= _cos + cos(!)
return r2d(Atan2(_sin/n, _cos/n))
end /*j*/
return r2d( Atan2( _sin/n, _cos/n) )

/*───────────────────────────────────────────────────────────────────────────────────────────*/
show: parse arg a,mA; _=format(ma, , showDig, 0) / 1
show: parse arg a,mA; _= format(ma, , showDig, 0) / 1
return left('angles='a, 30) "mean angle=" right(_, max(4, length(_)))
return left('angles='a, 30) "mean angle=" right(_, max(4, length(_) ) )

/*───────────────────────────────────────────────────────────────────────────────────────────*/
sin: procedure; parse arg x; x=r2r(x); numeric fuzz $fuzz(5, 3)
if x=pi*.5 then return 1; if x==pi*1.5 then return -1
sin: procedure; parse arg x; x= r2r(x); numeric fuzz $fuzz(5, 3)
if abs(x)=pi | x=0 then return 0; return .sinCos(x, x, +1)
if x=pi * .5 then return 1; if x==pi * 1.5 then return -1
if abs(x)=pi | x=0 then return 0; return .sinCos(x, x, +1)

/*───────────────────────────────────────────────────────────────────────────────────────────*/
sqrt: procedure; parse arg x; if x=0 then return 0; d=digits(); m.=9; numeric form; h=d+6
sqrt: procedure; parse arg x; if x=0 then return 0; d=digits(); m.=9; numeric form; h= d+6
numeric digits; 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*/
numeric digits; parse value format(x,2,1,,0) 'E0' with g "E" _ .; g= g * .5'e'_ % 2
do k=j+5 to 0 by -1; numeric digits m.k; g=(g+x/g)*.5; end /*k*/
do j=0 while h>9; m.j= h; h= h % 2 + 1; end /*j*/
do k=j+5 to 0 by -1; numeric digits m.k; g= (g + x/g) * .5; end /*k*/
return g</lang>
return g</syntaxhighlight>
''output''' &nbsp; when using the default input:
{{out|output|text=&nbsp; when using the default internal inputs:}}
<pre>
<pre>
angles=350 10 mean angle= 0
angles=350 10 mean angle= 0
Line 1,679: Line 1,929:
</pre>
</pre>
Note that with the increase in decimal digit precision, the 2<sup>nd</sup> mean angle changed dramatically from an earlier result. <br><br>
Note that with the increase in decimal digit precision, the 2<sup>nd</sup> mean angle changed dramatically from an earlier result. <br><br>

=={{header|Ring}}==
<syntaxhighlight lang="ring">
# Project : Averages/Mean angle

load "stdlib.ring"
decimals(6)
pi = 3.1415926535897
angles = [350,10]
see meanangle(angles, len(angles)) + nl
angles = [90,180,270,360]
see meanangle(angles, len(angles)) + nl
angles = [10,20,30]
see meanangle(angles, len(angles)) + nl
func meanangle(angles, n)
sumsin = 0
sumcos = 0
for i = 1 to n
sumsin = sumsin + sin(angles[i]*pi/180)
sumcos = sumcos + cos(angles[i]*pi/180)
next
return 180/pi*atan3(sumsin, sumcos)
func atan3(y,x)
if x <= 0
return sign(y)*pi/2
ok
if x>0
return atan(y/x)
else
if y>0
return atan(y/x)+pi
else
return atan(y/x)-pi
ok
ok
</syntaxhighlight>
Output:
<pre>
-0.000000
-90
20.000000
</pre>

=={{header|RPL}}==
≪ DEG → angles
≪ 0 1 angles SIZE '''FOR''' j
1 angles j GET R→C P→R + '''NEXT'''
angles SIZE / ARG
≫ ≫ ''''MEANG'''' STO
{{in}}
<pre>
{ 350 10 } MEANG
{ 90 180 270 360 } MEANG
{ 10 20 30 } MEANG
</pre>
{{out}}
<pre>
3: 0
2: -90
1: 20
</pre>


=={{header|Ruby}}==
=={{header|Ruby}}==
<lang ruby>require 'complex' # Superfluous in Ruby >= 2.0; complex is added to core.
<syntaxhighlight lang="ruby">require 'complex' # Superfluous in Ruby >= 2.0; complex is added to core.


def deg2rad(d)
def deg2rad(d)
Line 1,697: Line 2,010:
[[350, 10], [90, 180, 270, 360], [10, 20, 30]].each {|angles|
[[350, 10], [90, 180, 270, 360], [10, 20, 30]].each {|angles|
puts "The mean angle of %p is: %f degrees" % [angles, mean_angle(angles)]
puts "The mean angle of %p is: %f degrees" % [angles, mean_angle(angles)]
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 1,707: Line 2,020:
=={{header|Rust}}==
=={{header|Rust}}==


<lang rust>
<syntaxhighlight lang="rust">
use std::f64;
use std::f64;
// the macro is from
// the macro is from
Line 1,751: Line 2,064:
assert_diff!(20.0, mean_angle(&angles3), 0.001);
assert_diff!(20.0, mean_angle(&angles3), 0.001);
}
}
</syntaxhighlight>
</lang>


=={{header|Scala}}==
=={{header|Scala}}==
{{libheader|Scala}}<lang Scala>trait MeanAnglesComputation {
{{libheader|Scala}}<syntaxhighlight lang="scala">trait MeanAnglesComputation {
import scala.math.{Pi, atan2, cos, sin}
import scala.math.{Pi, atan2, cos, sin}


Line 1,772: Line 2,085:
assert(meanAngle(List(10, 20, 30)).round == 20, "Unexpected result with 10, 20, 30")
assert(meanAngle(List(10, 20, 30)).round == 20, "Unexpected result with 10, 20, 30")
println("Successfully completed without errors.")
println("Successfully completed without errors.")
}</lang>
}</syntaxhighlight>


=={{header|Scheme}}==
=={{header|Scheme}}==
Line 1,778: Line 2,091:
{{trans|Common Lisp}}
{{trans|Common Lisp}}


<lang scheme>
<syntaxhighlight lang="scheme">
(import (srfi 1 lists)) ;; use 'fold' from library
(import (srfi 1 lists)) ;; use 'fold' from library


Line 1,802: Line 2,115:
(display " is ") (display (mean-angle angles)) (newline))
(display " is ") (display (mean-angle angles)) (newline))
'((350 10) (90 180 270 360) (10 20 30)))
'((350 10) (90 180 270 360) (10 20 30)))
</syntaxhighlight>
</lang>


<pre>
<pre>
Line 1,811: Line 2,124:


=={{header|Seed7}}==
=={{header|Seed7}}==
<lang seed7>$ include "seed7_05.s7i";
<syntaxhighlight lang="seed7">$ include "seed7_05.s7i";
include "float.s7i";
include "float.s7i";
include "math.s7i";
include "math.s7i";
Line 1,840: Line 2,153:
writeln(meanAngle([] (90.0, 180.0, 270.0, 360.0)) digits 4);
writeln(meanAngle([] (90.0, 180.0, 270.0, 360.0)) digits 4);
writeln(meanAngle([] (10.0, 20.0, 30.0)) digits 4);
writeln(meanAngle([] (10.0, 20.0, 30.0)) digits 4);
end func;</lang>{{out}}
end func;</syntaxhighlight>{{out}}
0.0000
0.0000
90.0000
90.0000
Line 1,846: Line 2,159:


=={{header|Sidef}}==
=={{header|Sidef}}==
<lang ruby>func mean_angle(angles) {
<syntaxhighlight lang="ruby">func mean_angle(angles) {
atan2(
atan2(
Math.avg(angles.map{ .deg2rad.sin }...),
Math.avg(angles.map{ .deg2rad.sin }...),
Line 1,855: Line 2,168:
[[350,10], [90,180,270,360], [10,20,30]].each { |angles|
[[350,10], [90,180,270,360], [10,20,30]].each { |angles|
say "The mean angle of #{angles.dump} is: #{ '%.2f' % mean_angle(angles)} degrees"
say "The mean angle of #{angles.dump} is: #{ '%.2f' % mean_angle(angles)} degrees"
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 1,864: Line 2,177:


=={{header|Stata}}==
=={{header|Stata}}==
<lang stata>mata
<syntaxhighlight lang="stata">mata
function meanangle(a) {
function meanangle(a) {
return(arg(sum(exp(C(0,a)))))
return(arg(sum(exp(C(0,a)))))
}
}


deg=acos(-1)/180
deg=pi()/180


meanangle((350,10)*deg)/deg
meanangle((350,10)*deg)/deg
Line 1,877: Line 2,190:
meanangle((10,20,30)*deg)/deg
meanangle((10,20,30)*deg)/deg
20
20
end</lang>
end</syntaxhighlight>

=={{header|Swift}}==

<syntaxhighlight lang="swift">import Foundation

@inlinable public func d2r<T: FloatingPoint>(_ f: T) -> T { f * .pi / 180 }
@inlinable public func r2d<T: FloatingPoint>(_ f: T) -> T { f * 180 / .pi }

public func meanOfAngles(_ angles: [Double]) -> Double {
let cInv = 1 / Double(angles.count)
let (s, c) =
angles.lazy
.map(d2r)
.map({ (sin($0), cos($0)) })
.reduce(into: (0.0, 0.0), { $0.0 += $1.0; $0.1 += $1.1 })

return r2d(atan2(cInv * s, cInv * c))
}

let fmt = { String(format: "%lf", $0) }

print("Mean of angles (350, 10) => \(fmt(meanOfAngles([350, 10])))")
print("Mean of angles (90, 180, 270, 360) => \(fmt(meanOfAngles([90, 180, 270, 360])))")
print("Mean of angles (10, 20, 30) => \(fmt(meanOfAngles([10, 20, 30])))")</syntaxhighlight>

{{out}}

<pre>Mean of angles (350, 10) => -0.000000
Mean of angles (90, 180, 270, 360) => -90.000000
Mean of angles (10, 20, 30) => 20.000000</pre>


=={{header|Tcl}}==
=={{header|Tcl}}==
<lang tcl>proc meanAngle {angles} {
<syntaxhighlight lang="tcl">proc meanAngle {angles} {
set toRadians [expr {atan2(0,-1) / 180}]
set toRadians [expr {atan2(0,-1) / 180}]
set sumSin [set sumCos 0.0]
set sumSin [set sumCos 0.0]
Line 1,889: Line 2,232:
# Don't need to divide by counts; atan2() cancels that out
# Don't need to divide by counts; atan2() cancels that out
return [expr {atan2($sumSin, $sumCos) / $toRadians}]
return [expr {atan2($sumSin, $sumCos) / $toRadians}]
}</lang>
}</syntaxhighlight>
Demonstration code:
Demonstration code:
<lang tcl># A little pretty-printer
<syntaxhighlight lang="tcl"># A little pretty-printer
proc printMeanAngle {angles} {
proc printMeanAngle {angles} {
puts [format "mean angle of \[%s\] = %.2f" \
puts [format "mean angle of \[%s\] = %.2f" \
Line 1,899: Line 2,242:
printMeanAngle {350 10}
printMeanAngle {350 10}
printMeanAngle {90 180 270 360}
printMeanAngle {90 180 270 360}
printMeanAngle {10 20 30}</lang>
printMeanAngle {10 20 30}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 1,905: Line 2,248:
mean angle of [90, 180, 270, 360] = -90.00
mean angle of [90, 180, 270, 360] = -90.00
mean angle of [10, 20, 30] = 20.00
mean angle of [10, 20, 30] = 20.00
</pre>

=={{header|Vala}}==
<syntaxhighlight lang="vala">double meanAngle(double[] angles) {
double y_part = 0.0;
double x_part = 0.0;
for (int i = 0; i < angles.length; i++) {
x_part += Math.cos(angles[i] * Math.PI / 180.0);
y_part += Math.sin(angles[i] * Math.PI / 180.0);
}

return Math.atan2(y_part / angles.length, x_part / angles.length) * 180 / Math.PI;
}

void main() {
double[] angleSet1 = {350.0, 10.0};
double[] angleSet2 = {90.0, 180.0, 270.0, 360.0};
double[] angleSet3 = {10.0, 20.0, 30.0};

print("\nMean Angle for 1st set : %lf degrees", meanAngle(angleSet1));
print("\nMean Angle for 2nd set : %lf degrees", meanAngle(angleSet2));
print("\nMean Angle for 3rd set : %lf degrees\n", meanAngle(angleSet3));
}</syntaxhighlight>

{{out}}
<pre>
Mean Angle for 1st set : -0.000000 degrees
Mean Angle for 2nd set : -90.000000 degrees
Mean Angle for 3rd set : 20.000000 degrees
</pre>

=={{header|VBA}}==
<syntaxhighlight lang="vb">Option Base 1
Private Function mean_angle(angles As Variant) As Double
Dim sins() As Double, coss() As Double
ReDim sins(UBound(angles))
ReDim coss(UBound(angles))
For i = LBound(angles) To UBound(angles)
sins(i) = Sin(WorksheetFunction.Radians(angles(i)))
coss(i) = Cos(WorksheetFunction.Radians(angles(i)))
Next i
mean_angle = WorksheetFunction.Degrees( _
WorksheetFunction.Atan2( _
WorksheetFunction.sum(coss), _
WorksheetFunction.sum(sins)))
End Function
Public Sub main()
Debug.Print Format(mean_angle([{350,10}]), "##0")
Debug.Print Format(mean_angle([{90, 180, 270, 360}]), "##0")
Debug.Print Format(mean_angle([{10, 20, 30}]), "##0")
End Sub</syntaxhighlight>{{out}}
<pre>0
-90
20</pre>

=={{header|Visual Basic .NET}}==
{{trans|C#}}
<syntaxhighlight lang="vbnet">Imports System.Math

Module Module1

Function MeanAngle(angles As Double()) As Double
Dim x = angles.Sum(Function(a) Cos(a * PI / 180)) / angles.Length
Dim y = angles.Sum(Function(a) Sin(a * PI / 180)) / angles.Length
Return Atan2(y, x) * 180 / PI
End Function

Sub Main()
Dim printMean = Sub(x As Double()) Console.WriteLine("{0:0.###}", MeanAngle(x))
printMean({350, 10})
printMean({90, 180, 270, 360})
printMean({10, 20, 30})
End Sub

End Module</syntaxhighlight>
{{out}}
<pre>0
-90
20</pre>

=={{header|V (Vlang)}}==
{{trans|go}}
<syntaxhighlight lang="v (vlang)">import math
fn mean_angle(deg []f64) f64 {
mut ss, mut sc := f64(0), f64(0)
for x in deg {
s, c := math.sincos(x * math.pi / 180)
ss += s
sc += c
}
return math.atan2(ss, sc) * 180 / math.pi
}
fn main() {
for angles in [
[f64(350), 10],
[f64(90), 180, 270, 360],
[f64(10), 20, 30],
] {
println("The mean angle of $angles is: ${mean_angle(angles)} degrees")
}
}</syntaxhighlight>

{{out}}
<pre>
The mean angle of [350, 10] is: -2.6644363878955713e-14 degrees
The mean angle of [90, 180, 270, 360] is: -90 degrees
The mean angle of [10, 20, 30] is: 19.999999999999996 degree
</pre>

=={{header|Wren}}==
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">import "./fmt" for Fmt

var meanAngle = Fn.new { |angles|
var n = angles.count
var sinSum = 0
var cosSum = 0
for (angle in angles) {
sinSum = sinSum + (angle * Num.pi / 180).sin
cosSum = cosSum + (angle * Num.pi / 180).cos
}
return (sinSum/n).atan(cosSum/n) * 180 / Num.pi
}

var angles1 = [350, 10]
var angles2 = [90, 180, 270, 360]
var angles3 = [10, 20, 30]

var i = 1
for (angles in [angles1, angles2, angles3]) {
System.print("Mean for angles %(i) is : %(Fmt.f(6, meanAngle.call(angles), 2))")
i = i + 1
}</syntaxhighlight>

{{out}}
<pre>
Mean for angles 1 is : -0.00
Mean for angles 2 is : -90.00
Mean for angles 3 is : 20.00
</pre>
</pre>


=={{header|XPL0}}==
=={{header|XPL0}}==
<lang XPL0>include c:\cxpl\codes;
<syntaxhighlight lang="xpl0">include c:\cxpl\codes;


def Pi = 3.14159265358979323846;
def Pi = 3.14159265358979323846;
Line 1,929: Line 2,414:
RlOut(0, MeanAng([4, 90, 180, 270, 360])); CrLf(0);
RlOut(0, MeanAng([4, 90, 180, 270, 360])); CrLf(0);
RlOut(0, MeanAng([3, 10, 20, 30])); CrLf(0);
RlOut(0, MeanAng([3, 10, 20, 30])); CrLf(0);
]</lang>
]</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 1,940: Line 2,425:


=={{header|zkl}}==
=={{header|zkl}}==
<lang zkl>fcn meanA(a1,a2,etc){
<syntaxhighlight lang="zkl">fcn meanA(a1,a2,etc){
as:=vm.arglist.pump(List,"toFloat","toRad");
as:=vm.arglist.pump(List,"toFloat","toRad");
n:=as.len();
n:=as.len();
Line 1,946: Line 2,431:
.atan2(as.apply("cos").sum(0.0)/n)
.atan2(as.apply("cos").sum(0.0)/n)
.toDeg()
.toDeg()
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 1,956: Line 2,441:
20
20
</pre>
</pre>

[[Category:Geometry]]

Latest revision as of 10:47, 7 November 2023

Task
Averages/Mean angle
You are encouraged to solve this task according to the task description, using any language you may know.

When calculating the average or mean of an angle one has to take into account how angles wrap around so that any angle in degrees plus any integer multiple of 360 degrees is a measure of the same angle.

If one wanted an average direction of the wind over two readings where the first reading was of 350 degrees and the second was of 10 degrees then the average of the numbers is 180 degrees, whereas if you can note that 350 degrees is equivalent to -10 degrees and so you have two readings at 10 degrees either side of zero degrees leading to a more fitting mean angle of zero degrees.

To calculate the mean angle of several angles:

  1. Assume all angles are on the unit circle and convert them to complex numbers expressed in real and imaginary form.
  2. Compute the mean of the complex numbers.
  3. Convert the complex mean to polar coordinates whereupon the phase of the complex mean is the required angular mean.


(Note that, since the mean is the sum divided by the number of numbers, and division by a positive real number does not affect the angle, you can also simply compute the sum for step 2.)

You can alternatively use this formula:

Given the angles the mean is computed by
Task
  1. write a function/method/subroutine/... that given a list of angles in degrees returns their mean angle.
    (You should use a built-in function if you have one that does this for degrees or radians).
  2. Use the function to compute the means of these lists of angles (in degrees):
    •   [350, 10]
    •   [90, 180, 270, 360]
    •   [10, 20, 30]
  3. Show your output here.
See also



11l

Translation of: C#
F mean_angle(angles)
   V x = sum(angles.map(a -> cos(radians(a)))) / angles.len
   V y = sum(angles.map(a -> sin(radians(a)))) / angles.len
   R degrees(atan2(y, x))

print(mean_angle([350, 10]))
print(mean_angle([90, 180, 270, 360]))
print(mean_angle([10, 20, 30]))
Output:
-1.61481e-15
-90
20

Ada

An implementation based on the formula using the "Arctan" (atan2) function, thus avoiding complex numbers:

with Ada.Text_IO, Ada.Numerics.Generic_Elementary_Functions;

procedure Mean_Angles is

   type X_Real is digits 4;      -- or more digits for improved precision
   subtype Real is X_Real range 0.0 .. 360.0; -- the range of interest
   type Angles is array(Positive range <>) of Real;

   procedure Put(R: Real) is
      package IO is new Ada.Text_IO.Float_IO(Real);
   begin
      IO.Put(R, Fore => 3, Aft => 2, Exp => 0);
   end Put;

   function Mean_Angle(A: Angles) return Real is
      Sin_Sum, Cos_Sum: X_Real := 0.0; -- X_Real since sums might exceed 360.0
      package Math is new Ada.Numerics.Generic_Elementary_Functions(Real);
      use Math;
   begin
      for I in A'Range loop
        Sin_Sum := Sin_Sum + Sin(A(I), Cycle => 360.0);
        Cos_Sum := Cos_Sum + Cos(A(I), Cycle => 360.0);
      end loop;
      return Arctan(Sin_Sum / X_Real(A'Length), Cos_Sum / X_Real(A'Length),
                    Cycle => 360.0);
        -- may raise Ada.Numerics.Argument_Error if inputs are
        -- numerically instable, e.g., when Cos_Sum is 0.0
   end Mean_Angle;

begin
   Put(Mean_Angle((10.0, 20.0, 30.0)));     Ada.Text_IO.New_Line;    -- 20.00
   Put(Mean_Angle((10.0, 350.0)));          Ada.Text_IO.New_Line;    --  0.00
   Put(Mean_Angle((90.0, 180.0, 270.0, 360.0))); -- Ada.Numerics.Argument_Error!
end Mean_Angles;
Output:
 20.00
  0.00

raised ADA.NUMERICS.ARGUMENT_ERROR : a-ngelfu.adb:427 instantiated at mean_angles.adb:17

Aime

real
mean(list l)
{
    integer i;
    real x, y;

    x = y = 0;

    i = 0;
    while (i < l_length(l)) {
        x += Gcos(l[i]);
        y += Gsin(l[i]);
        i += 1;
    }

    return Gatan2(y / l_length(l), x / l_length(l));
}

integer
main(void)
{
    o_form("mean of 1st set: /d6/\n", mean(l_effect(350, 10)));
    o_form("mean of 2nd set: /d6/\n", mean(l_effect(90, 180, 270, 360)));
    o_form("mean of 3rd set: /d6/\n", mean(l_effect(10, 20, 30)));

    return 0;
}
Output:
mean of 1st set: -.000000
mean of 2nd set: -90
mean of 3rd set: 19.999999

ALGOL 68

Works with: ALGOL 68 version Revision 1
Works with: ALGOL 68G version Any - tested with release algol68g-2.8.3.
Translation of: C – Note: This specimen retains the original C coding style

File: Averages_Mean_angle.a68

#!/usr/bin/a68g --script #
# -*- coding: utf-8 -*- #

PROC mean angle = ([]#LONG# REAL angles)#LONG# REAL:
(
  INT size = UPB angles - LWB angles + 1;
  #LONG# REAL y part := 0, x part := 0;
  FOR i FROM LWB angles TO UPB angles DO
      x part +:= #long# cos (angles[i] * #long# pi / 180);
      y part +:= #long# sin (angles[i] * #long# pi / 180)
  OD;
 
  #long# arc tan2 (y part / size, x part / size) * 180 / #long# pi
);
 
main:
(
  []#LONG# REAL angle set 1 = ( 350, 10 );
  []#LONG# REAL angle set 2 = ( 90, 180, 270, 360);
  []#LONG# REAL angle set 3 = ( 10, 20, 30);
 
  FORMAT summary fmt=$"Mean angle for "g" set :"-zd.ddddd" degrees"l$;
  printf ((summary fmt,"1st", mean angle (angle set 1)));
  printf ((summary fmt,"2nd", mean angle (angle set 2)));
  printf ((summary fmt,"3rd", mean angle (angle set 3)))
)
Output:
Mean angle for 1st set : -0.00000 degrees
Mean angle for 2nd set :-90.00000 degrees
Mean angle for 3rd set : 20.00000 degrees

AutoHotkey

Works with: AutoHotkey 1.1
Angles :=  [[350, 10], [90, 180, 270, 360], [10, 20, 30]]
MsgBox, % MeanAngle(Angles[1]) "`n"
	. MeanAngle(Angles[2]) "`n" 
	. MeanAngle(Angles[3]) 

MeanAngle(a, x=0, y=0) {
	static c := ATan(1) / 45
	for k, v in a {
		x += Cos(v * c) / a.MaxIndex()
		y += Sin(v * c) / a.MaxIndex()
	}
	return atan2(x, y) / c
}

atan2(x, y) {
   return dllcall("msvcrt\atan2", "Double",y, "Double",x, "CDECL Double")
}

Output:

-0.000000
-90.000000
20.000000

AWK

#!/usr/bin/awk -f
{
    PI = atan2(0,-1);
    x=0.0; y=0.0;
    for (i=1; i<=NF; i++) {	
	p = $i*PI/180.0;
	x += sin(p);
	y += cos(p);
    }
    p = atan2(x,y)*180.0/PI;	
    if (p<0) p += 360;
    print p;
}
 echo 350 10 | ./mean_angle.awk 
360
 echo 10 20 30 | ./mean_angle.awk 
20
 echo 90 180 270 360  | ./mean_angle.awk 
270

BBC BASIC

      *FLOAT 64
      DIM angles(3)
      angles() = 350,10
      PRINT FNmeanangle(angles(), 2)
      angles() = 90,180,270,360
      PRINT FNmeanangle(angles(), 4)
      angles() = 10,20,30
      PRINT FNmeanangle(angles(), 3)
      END
      
      DEF FNmeanangle(angles(), N%)
      LOCAL I%, sumsin, sumcos
      FOR I% = 0 TO N%-1
        sumsin += SINRADangles(I%)
        sumcos += COSRADangles(I%)
      NEXT
      = DEGFNatan2(sumsin, sumcos)
      
      DEF FNatan2(y,x) : ON ERROR LOCAL = SGN(y)*PI/2
      IF x>0 THEN = ATN(y/x) ELSE IF y>0 THEN = ATN(y/x)+PI ELSE = ATN(y/x)-PI
Output:
-1.61480993E-15
       -90
        20

C

#include<math.h>
#include<stdio.h>

double
meanAngle (double *angles, int size)
{
  double y_part = 0, x_part = 0;
  int i;

  for (i = 0; i < size; i++)
    {
      x_part += cos (angles[i] * M_PI / 180);
      y_part += sin (angles[i] * M_PI / 180);
    }

  return atan2 (y_part / size, x_part / size) * 180 / M_PI;
}

int
main ()
{
  double angleSet1[] = { 350, 10 };
  double angleSet2[] = { 90, 180, 270, 360};
  double angleSet3[] = { 10, 20, 30};

  printf ("\nMean Angle for 1st set : %lf degrees", meanAngle (angleSet1, 2));
  printf ("\nMean Angle for 2nd set : %lf degrees", meanAngle (angleSet2, 4));
  printf ("\nMean Angle for 3rd set : %lf degrees\n", meanAngle (angleSet3, 3));
  return 0;
}
Output:
Mean Angle for 1st set : -0.000000 degrees
Mean Angle for 2nd set : -90.000000 degrees
Mean Angle for 3rd set : 20.000000 degrees

C#

using System;
using System.Linq;
using static System.Math;
class Program
{
    static double MeanAngle(double[] angles)
    {
        var x = angles.Sum(a => Cos(a * PI / 180)) / angles.Length;
        var y = angles.Sum(a => Sin(a * PI / 180)) / angles.Length;
        return Atan2(y, x) * 180 / PI;
    }
    static void Main()
    {
        Action<double[]> printMean = x => Console.WriteLine("{0:0.###}", MeanAngle(x));
        printMean(new double[] { 350, 10 });
        printMean(new double[] { 90, 180, 270, 360 });
        printMean(new double[] { 10, 20, 30 });
    }
}
Output:
0
-90
20

C++

Translation of: C#
#include <iomanip>
#include <iostream>
#include <vector>

#define _USE_MATH_DEFINES
#include <math.h>

template<typename C>
double meanAngle(const C& c) {
    auto it = std::cbegin(c);
    auto end = std::cend(c);

    double x = 0.0;
    double y = 0.0;
    double len = 0.0;
    while (it != end) {
        x += cos(*it * M_PI / 180);
        y += sin(*it * M_PI / 180);
        len++;

        it = std::next(it);
    }

    return atan2(y, x) * 180 / M_PI;
}

void printMean(std::initializer_list<double> init) {
    std::cout << std::fixed << std::setprecision(3) << meanAngle(init) << '\n';
}

int main() {
    printMean({ 350, 10 });
    printMean({ 90, 180, 270, 360 });
    printMean({ 10, 20, 30 });

    return 0;
}
Output:
-0.000
-90.000
20.000

Clojure

(defn mean-fn
  [k coll]
  (let [n (count coll)
        trig (get {:sin #(Math/sin %) :cos #(Math/cos %)} k)]
    (* (/ 1 n) (reduce + (map trig coll)))))

(defn mean-angle
  [degrees]
  (let [radians (map #(Math/toRadians %) degrees)
        a (mean-fn :sin radians)
        b (mean-fn :cos radians)]
    (Math/toDegrees (Math/atan2 a b))))

Example:

(mean-angle [350 10])
;=> -1.614809932057922E-15

(mean-angle [90 180 270 360])
;=> -90.0

(mean-angle [10 20 30])
;=> 19.999999999999996

Common Lisp

(defun average (list)
  (/ (reduce #'+ list) (length list)))

(defun radians (angle)
  (* pi 1/180 angle))

(defun degrees (angle)
  (* (/ 180 pi) angle))

(defun mean-angle (angles)
  (let* ((angles (map 'list #'radians angles))
	 (cosines (map 'list #'cos angles))
	 (sines (map 'list #'sin angles)))
    (degrees (atan (average sines) (average cosines)))))

(loop for angles in '((350 10) (90 180 270 360) (10 20 30))
   do (format t "~&The mean angle of ~a is ~$°." angles (mean-angle angles)))

;; or using complex numbers (cis and phase)

(defun mean-angle-2 (angles)
    (degrees (phase (reduce #'+ angles :key (lambda (deg) (cis (radians deg)))))))
Output:
The mean angle of (350 10) is -0.00°.
The mean angle of (90 180 270 360) is -90.00°.
The mean angle of (10 20 30) is 20.00°.

D

import std.stdio, std.algorithm, std.complex;
import std.math: PI;

auto radians(T)(in T d) pure nothrow @nogc { return d * PI / 180; }
auto degrees(T)(in T r) pure nothrow @nogc { return r * 180 / PI; }

real meanAngle(T)(in T[] D) pure nothrow @nogc {
    immutable t = reduce!((a, d) => a + d.radians.expi)(0.complex, D);
    return (t / D.length).arg.degrees;
}

void main() {
    foreach (angles; [[350, 10], [90, 180, 270, 360], [10, 20, 30]])
        writefln("The mean angle of %s is: %.2f degrees",
                 angles, angles.meanAngle);
}
Output:
The mean angle of [350, 10] is: -0.00 degrees
The mean angle of [90, 180, 270, 360] is: 90.00 degrees
The mean angle of [10, 20, 30] is: 20.00 degrees

Delphi

See #Pascal.

EasyLang

Translation of: C
func mean ang[] .
   for ang in ang[]
      x += cos ang
      y += sin ang
   .
   return atan2 (y / len ang[]) (x / len ang[])
.
print mean [ 350 10 ]
print mean [ 90 180 270 360 ]
print mean [ 10 20 30 ]

EchoLisp

(define-syntax-rule  (deg->radian deg) (* deg 1/180 PI))
(define-syntax-rule  (radian->deg rad) (* 180 (/ PI) rad))

(define (mean-angles angles)
	(radian->deg 
          (angle 
	    (for/sum ((a angles)) (make-polar 1 (deg->radian a))))))

(mean-angles '( 350 10))
     -0
(mean-angles '[90 180 270 360])
     -90
(mean-angles '[10 20 30])
     20

Elixir

defmodule MeanAngle do
  def mean_angle(angles) do
    rad_angles = Enum.map(angles, &deg_to_rad/1)
    sines = rad_angles |> Enum.map(&:math.sin/1) |> Enum.sum
    cosines = rad_angles |> Enum.map(&:math.cos/1) |> Enum.sum

    rad_to_deg(:math.atan2(sines, cosines))
  end

  defp deg_to_rad(a) do
    (:math.pi/180) * a
  end

  defp rad_to_deg(a) do
    (180/:math.pi) * a
  end
end

IO.inspect MeanAngle.mean_angle([10, 350])
IO.inspect MeanAngle.mean_angle([90, 180, 270, 360])
IO.inspect MeanAngle.mean_angle([10, 20, 30])
Output:
-1.614809932057922e-15
-90.0
19.999999999999996

Erlang

The function from_degrees/1 is used to solve Averages/Mean_time_of_day. Please keep backwards compatibility when editing. Or update the other module, too.

-module( mean_angle ).
-export( [from_degrees/1, task/0] ).

from_degrees( Angles ) ->
	Radians = [radians(X) || X <- Angles],
	Sines = [math:sin(X) || X <- Radians],
	Coses = [math:cos(X) || X <- Radians],
	degrees( math:atan2( average(Sines), average(Coses) ) ).

task() ->
	Angles = [[350, 10], [90, 180, 270, 360], [10, 20, 30]],
	[io:fwrite( "Mean angle of ~p is: ~p~n", [X, erlang:round(from_degrees(X))] ) || X <- Angles].


average( List ) -> lists:sum( List ) / erlang:length( List ).

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

radians( Degrees ) -> Degrees * math:pi() / 180.
Output:
16> mean_angle:task().
Mean angle of [350,10] is: 0
Mean angle of [90,180,270,360] is: -90
Mean angle of [10,20,30] is: 20

Euler Math Toolbox

>function meanangle (a) ...
$  z=sum(exp(rad(a)*I));
$  if z~=0 then error("Not meaningful");
$  else return deg(arg(z))
$  endfunction
>meanangle([350,10])
 0
>meanangle([90,180,270,360])
 Error : Not meaningful
 
 Error generated by error() command
 
 Error in function meanangle in line
 if z~=0 then error("Not meaningful");
>meanangle([10,20,30])
 20

Euphoria

Works with: OpenEuphoria
include std/console.e
include std/mathcons.e

sequence AngleList = {{350,10},{90,180,270,360},{10,20,30}}

function atan2(atom y, atom x)
	return 2*arctan((sqrt(power(x,2)+power(y,2)) - x)/y)
end function

function MeanAngle(sequence angles)
	atom x = 0, y = 0
	integer l = length(angles)
	
	for i = 1 to length(angles) do
		x += cos(angles[i] * PI / 180)
		y += sin(angles[i] * PI / 180)
	end for
	
	return atan2(y / l, x / l) * 180 / PI
end function 

for i = 1 to length(AngleList) do
	printf(1,"Mean Angle for set %d:  %3.5f\n",{i,MeanAngle(AngleList[i])})
end for

if getc(0) then end if
Output:
Mean Angle for set 1:  0.00000
Mean Angle for set 2:  -90.00000
Mean Angle for set 3:  20.00000

F#

open System
open System.Numerics

let deg2rad d = d * Math.PI / 180.
let rad2deg r = r * 180. / Math.PI

[<EntryPoint>]
let main argv =
    let makeComplex = fun r ->  Complex.FromPolarCoordinates(1., r)
    argv
    |> Seq.map (Double.Parse >> deg2rad >> makeComplex)
    |> Seq.fold (fun x y -> Complex.Add(x,y)) Complex.Zero
    |> fun c -> c.Phase |> rad2deg
    |> printfn "Mean angle for [%s]: %g°" (String.Join("; ",argv))
    0
Output:
>RosettaCode 350 10
Mean angle for [350; 10]: -2.74518e-14°

>RosettaCode 10 20 30
Mean angle for [10; 20; 30]: 20°

>RosettaCode 90 180 270 360
Mean angle for [90; 180; 270; 360]: -90°

Factor

USING: formatting kernel math math.functions math.libm math.trig
sequences ;

: mean-angle ( seq -- x )
    [ deg>rad ] map [ [ sin ] map-sum ] [ [ cos ] map-sum ]
    [ length ] tri recip [ * ] curry bi@ fatan2 rad>deg ;

: show ( seq -- )
    dup mean-angle "The mean angle of %u is: %f°\n" printf ;

{ { 350 10 } { 90 180 270 360 } { 10 20 30 } } [ show ] each
Output:
The mean angle of { 350 10 } is: -0.000000°
The mean angle of { 90 180 270 360 } is: -90.000000°
The mean angle of { 10 20 30 } is: 20.000000°

Fortran

Please find the example output along with the build instructions in the comments at the start of the FORTRAN 2008 source. Compiler: gfortran from the GNU compiler collection. Command interpreter: bash.

!-*- mode: compilation; default-directory: "/tmp/" -*-
!Compilation started at Mon Jun  3 18:07:59
!
!a=./f && make $a && OMP_NUM_THREADS=2 $a
!gfortran -std=f2008 -Wall -fopenmp -ffree-form -fall-intrinsics -fimplicit-none f.f08 -o f
!  -7.80250048E-06         350          10
!   90.0000000              90         180         270         360
!   19.9999962              10          20          30
!
!Compilation finished at Mon Jun  3 18:07:59

program average_angles
  !real(kind=8), parameter :: TAU = 6.283185307179586232 ! http://tauday.com/
  !integer, dimension(13), parameter :: test_data = (/2,350,10, 4,90,180,270,360, 3,10,20,30, 0/)
  !integer :: i, j, n
  !complex(kind=16) :: some
  !real(kind=8) :: angle
  real, parameter :: TAU = 6.283185307179586232 ! http://tauday.com/
  integer, dimension(13), parameter :: test_data = (/2,350,10, 4,90,180,270,360, 3,10,20,30, 0/)
  integer :: i, j, n
  complex :: some
  real :: angle
  i = 1
  n = int(test_data(i))
  do while (0 .lt. n)
    some = 0
    do j = 1, n
      angle = (TAU/360)*test_data(i+j)
      some = some + cmplx(cos(angle), sin(angle))
    end do
    some = some / n
    write(6,*)(360/TAU)*atan2(aimag(some), real(some)),test_data(i+1:i+n)
    i = i + n + 1
    n = int(test_data(i))
  end do
end program average_angles

FreeBASIC

' FB 1.05.0 Win64

Const PI As Double = 3.1415926535897932

Function MeanAngle(angles() As Double) As Double
  Dim As Integer length = Ubound(angles) - Lbound(angles) + 1
  Dim As Double sinSum = 0.0
  Dim As Double cosSum = 0.0
  For i As Integer = LBound(angles) To UBound(angles)
    sinSum += Sin(angles(i) * PI / 180.0)
    cosSum += Cos(angles(i) * PI / 180.0)    
  Next
  Return Atan2(sinSum / length, cosSum / length) * 180.0 / PI
End Function

Dim As Double angles1(1 To 2) = {350, 10}
Dim As Double angles2(1 To 4) = {90, 180, 270, 360}
Dim As Double angles3(1 To 3) = {10, 20, 30}

Print Using "Mean for angles 1 is : ####.## degrees"; MeanAngle(angles1())
Print Using "Mean for angles 2 is : ####.## degrees"; MeanAngle(angles2())
Print Using "Mean for angles 3 is : ####.## degrees"; MeanAngle(angles3())
Print
Print "Press any key to quit the program"
Sleep
Output:
Mean for angles 1 is :   -0.00 degrees
Mean for angles 2 is :  -90.00 degrees
Mean for angles 3 is :   20.00 degrees

Go

Complex

package main

import (
	"fmt"
	"math"
	"math/cmplx"
)

func deg2rad(d float64) float64 { return d * math.Pi / 180 }
func rad2deg(r float64) float64 { return r * 180 / math.Pi }

func mean_angle(deg []float64) float64 {
	sum := 0i
	for _, x := range deg {
		sum += cmplx.Rect(1, deg2rad(x))
	}
	return rad2deg(cmplx.Phase(sum))
}

func main() {
	for _, angles := range [][]float64{
		{350, 10},
		{90, 180, 270, 360},
		{10, 20, 30},
	} {
		fmt.Printf("The mean angle of %v is: %f degrees\n", angles, mean_angle(angles))
	}
}
Output:
The mean angle of [350 10] is: -0.000000 degrees
The mean angle of [90 180 270 360] is: -90.000000 degrees
The mean angle of [10 20 30] is: 20.000000 degrees

Atan2

A mean_angle function that could be substituted above. Functions deg2rad and rad2deg are not used here but there is no runtime advantage either way to using them or not. Inlining should result in eqivalent code being generated. Also the Go Atan2 library function has no limits on the arguments so there is no need to divide by the number of elements.

func mean_angle(deg []float64) float64 {
	var ss, sc float64
	for _, x := range deg {
		s, c := math.Sincos(x * math.Pi / 180)
		ss += s
		sc += c
	}
	return math.Atan2(ss, sc) * 180 / math.Pi
}

Groovy

import static java.lang.Math.*
def meanAngle = {
    atan2( it.sum { sin(it * PI / 180) } / it.size(), it.sum { cos(it * PI / 180) } / it.size()) * 180 / PI
}

Test:

def verifyAngle = { angles ->
    def ma = meanAngle(angles)
    printf("Mean Angle for $angles: %5.2f%n", ma)
    round(ma * 100) / 100.0
}
assert verifyAngle([350, 10]) == -0
assert verifyAngle([90, 180, 270, 360]) == -90
assert verifyAngle([10, 20, 30]) == 20
Output:
Mean Angle for [350, 10]: -0.00
Mean Angle for [90, 180, 270, 360]: -90.00
Mean Angle for [10, 20, 30]: 20.00

Haskell

import Data.Complex (cis, phase)

meanAngle
  :: RealFloat c
  => [c] -> c
meanAngle = (/ pi) . (* 180) . phase . sum . map (cis . (/ 180) . (* pi))

main :: IO ()
main =
  mapM_
    (\angles ->
        putStrLn $
        "The mean angle of " ++
        show angles ++ " is: " ++ show (meanAngle angles) ++ " degrees")
    [[350, 10], [90, 180, 270, 360], [10, 20, 30]]
Output:
The mean angle of [350.0,10.0] is: -2.745176884498468e-14 degrees
The mean angle of [90.0,180.0,270.0,360.0] is: -90.0 degrees
The mean angle of [10.0,20.0,30.0] is: 19.999999999999996 degrees


Alternative Solution: This solution gives an insight about using factoring, many small functions like Forth and using function composition.

-- file: trigdeg.fs

deg2rad deg = deg*pi/180.0
rad2deg rad = rad*180.0/pi

sind = sin . deg2rad
cosd = cos . deg2rad
tand = tan . deg2rad
atand = rad2deg . atan
atan2d y x = rad2deg (atan2 y x )

avg_angle angles = atan2d y x
    where
    y = mean (map sind angles) 
    x = mean (map cosd angles)

-- End of trigdeg.fs --------
Output:

-- GHCI shell  $ ghci

Prelude> :load trigdeg.hs 
[1 of 1] Compiling Main             ( trigdeg.hs, interpreted )
Ok, modules loaded: Main.
*Main> 
*Main> avg_angle [350.0, 10.0]
-2.745176884498468e-14
*Main> 
*Main> avg_angle [90.0, 180.0, 270.0, 360.0 ]
-90.0
*Main> mean [10.0, 20.0, 30.0]
20.0
*Main>

Icon and Unicon

procedure main(A)
    write("Mean angle is ",meanAngle(A))
end

procedure meanAngle(A)
    every (sumSines := 0.0) +:= sin(dtor(!A))
    every (sumCosines := 0.0) +:= cos(dtor(!A))
    return rtod(atan(sumSines/*A,sumCosines/*A))
end

Sample runs:

->ama 10 350
Mean angle is -2.745176884498468e-14
->ama 90 180 270 360
Mean angle is -90.0
->ama 10 20 30
Mean angle is 20.0

IDL

function mean_angle, phi
        z = total(exp(complex(0,phi*!dtor)))
	return, atan(imaginary(z),real_part(z))*!radeg
end
Output:
IDL> print, mean_angle([350, 10])
 -7.80250e-06
IDL> print, mean_angle([90, 180, 270, 360])
      90.0000
IDL> print, mean_angle([10, 20, 30])
      20.0000

J

avgAngleD=: 360|(_1 { [: (**|)&.+.@(+/ % #)&.(*.inv) 1,.])&.(1r180p1&*)

This verb can be represented as simpler component verbs, for example:

rfd=: 1r180p1&*                                          NB. convert angle to radians from degrees
toComplex=: *.inv                                        NB. maps integer pairs as length, complex angle (in radians)
mean=: +/ % #                                            NB. calculate arithmetic mean
roundComplex=: (* * |)&.+.                               NB. discard an extraneous least significant bit of precision from a complex value whose magnitude is in the vicinity of 1
avgAngleR=: _1 { [: roundComplex@mean&.toComplex 1 ,. ]  NB. calculate average angle in radians
avgAngleD=: 360|avgAngleR&.rfd                           NB. calculate average angle in degrees

Example use:

   avgAngleD 10 350
0
   avgAngleD 90 180 270 360 NB. result not meaningful
0
   avgAngleD 10 20 30
20
   avgAngleD 20 350
5
   avgAngleD 10 340
355

Notes:

(**|)&.+. is an expression to discard an extraneous least significant bit of precision from a complex value whose magnitude is in the vicinity of 1.

(+/ % #) finds the (Pythagorean) mean

verb&.(*.inv) maps integer pairs as length,complex angle (in radians) and uses the verb in the domain of complex numbers, and then maps the result back to length,angle.

(1,.]) prefixes every value in a list with 1 (forming a two column table)

(_1 { verb) takes the last item from the result of the verb (and note that after we average our complex values and convert them back to length/angle format, we will be working with a list of two elements: length and angle -- and we do not care about length, which will usually be less than 1).

verb&.(1r180p1&*) converts its argument from degrees to radians, uses the verb in the radian domain, then converts the result of that argument back to degrees.

360|verb ensures that the result is not negative and is also less than 360

Java

Translation of: NetRexx
Works with: Java version 7+
import java.util.Arrays;

public class AverageMeanAngle {

    public static void main(String[] args) {
        printAverageAngle(350.0, 10.0);
        printAverageAngle(90.0, 180.0, 270.0, 360.0);
        printAverageAngle(10.0, 20.0, 30.0);
        printAverageAngle(370.0);
        printAverageAngle(180.0);
    }

    private static void printAverageAngle(double... sample) {
        double meanAngle = getMeanAngle(sample);
        System.out.printf("The mean angle of %s is %s%n", Arrays.toString(sample), meanAngle);
    }

    public static double getMeanAngle(double... anglesDeg) {
        double x = 0.0;
        double y = 0.0;

        for (double angleD : anglesDeg) {
            double angleR = Math.toRadians(angleD);
            x += Math.cos(angleR);
            y += Math.sin(angleR);
        }
        double avgR = Math.atan2(y / anglesDeg.length, x / anglesDeg.length);
        return Math.toDegrees(avgR);
    }
}
Output:
The mean angle of [350.0, 10.0] is -1.614809932057922E-15
The mean angle of [90.0, 180.0, 270.0, 360.0] is -90.0
The mean angle of [10.0, 20.0, 30.0] is 19.999999999999996
The mean angle of [370.0] is 9.999999999999977
The mean angle of [180.0] is 180.0

JavaScript

atan2

function sum(a) {
    var s = 0;
    for (var i = 0; i < a.length; i++) s += a[i];
    return s;
} 

function degToRad(a) {
    return Math.PI / 180 * a;
}

function meanAngleDeg(a) {
    return 180 / Math.PI * Math.atan2(
        sum(a.map(degToRad).map(Math.sin)) / a.length,
        sum(a.map(degToRad).map(Math.cos)) / a.length
    );
}

var a = [350, 10], b = [90, 180, 270, 360],  c = [10, 20, 30];
console.log(meanAngleDeg(a));
console.log(meanAngleDeg(b));
console.log(meanAngleDeg(c));
Output:
-1.614809932057922e-15
-90
19.999999999999996

jq

Works with: jq version 1.4

To avoid anomalies, the following is designed to assign the null value as the mean angle in cases such as [0, 180].

Generic Infrastructure

def pi: 4 * (1|atan);

def deg2rad: . * pi / 180;
 
def rad2deg: if . == null then null else . * 180 / pi end;

# Input: [x,y] (special handling of x==0)
# Output: [r, theta] where theta may be null
def to_polar:
  if .[0] == 0
  then [1, if .[1] > 5e-14 then pi/2 elif .[1] < -5e-14 then -pi/2 else null end]
  else [1, ((.[1]/.[0]) | atan)]
  end;

def from_polar: .[1] | [ cos, sin];

def abs: if . < 0 then - . else . end;
  
def summation(f): map(f) | add;

Mean Angle

# input: degrees
def mean_angle:
  def round:
    if . == null then null
    elif . < 0 then -1 * ((- .) | round) | if . == -0 then 0 else . end
    else ((. + 3e-14) | floor) as $x
    | if ($x - .) | abs < 3e-14 then $x else . end
    end;

  map( [1, deg2rad] | from_polar)
  | [ summation(.[0]), summation(.[1]) ]
  | to_polar
  | .[1]
  | rad2deg
  | round;

Examples

([350, 10], [90, 180, 270, 360], [10, 20, 30])
| "The mean angle of \(.) is: \(mean_angle)"
Output:
jq -r -n -f Mean_angle.jq
The mean angle of [350,10] is: 0
The mean angle of [90,180,270,360] is: null
The mean angle of [10,20,30] is: 20

Julia

Julia has built-in functions sind and cosd to compute the sine and cosine of angles specified in degrees accurately (avoiding the roundoff errors incurred in conversion to radians), and a built-in function to convert radians to degrees (or vice versa). Using these:

using Statistics
meandegrees(degrees) = rad2deg(atan(mean(sind.(degrees)), mean(cosd.(degrees))))

The output is:

julia> meandegrees([350, 10])
0.0

julia> meandegrees([90, 180, 270, 360]])
0.0

julia> meandegrees([10, 20, 30]])
19.999999999999996

(Note that the mean of 90°, 180°, 270°, and 360° gives zero because of the lack of roundoff errors in the sind function, since the standard-library atan2(0,0) value is zero. Many of the other languages report an average of 90° or –90° in this case due to rounding errors.)

Kotlin

// version 1.0.5-2

fun meanAngle(angles: DoubleArray): Double {
    val sinSum = angles.sumByDouble {  Math.sin(it * Math.PI / 180.0) }
    val cosSum = angles.sumByDouble {  Math.cos(it * Math.PI / 180.0) }
    return Math.atan2(sinSum / angles.size, cosSum / angles.size) * 180.0 / Math.PI
}

fun main(args: Array<String>) {
    val angles1 = doubleArrayOf(350.0, 10.0)
    val angles2 = doubleArrayOf(90.0, 180.0, 270.0, 360.0)
    val angles3 = doubleArrayOf(10.0, 20.0, 30.0)
    val fmt  = "%.2f degrees" // format results to 2 decimal places
    println("Mean for angles 1 is ${fmt.format(meanAngle(angles1))}")
    println("Mean for angles 2 is ${fmt.format(meanAngle(angles2))}")
    println("Mean for angles 3 is ${fmt.format(meanAngle(angles3))}")
}
Output:
Mean for angles 1 is -0.00 degrees
Mean for angles 2 is -90.00 degrees
Mean for angles 3 is 20.00 degrees

Liberty BASIC

global Pi
Pi =3.1415926535

print "Mean Angle( "; chr$( 34); "350,10"; chr$( 34); ") = ";         using( "###.#", meanAngle( "350,10")); " degrees."             '          0
print "Mean Angle( "; chr$( 34); "90,180,270,360"; chr$( 34); ") = "; using( "###.#", meanAngle( "90,180,270,360")); " degrees."  '        -90
print "Mean Angle( "; chr$( 34); "10,20,30"; chr$( 34); ") = ";       using( "###.#", meanAngle( "10,20,30")); " degrees."        '         20

end

function meanAngle( angles$)
   term =1
   while word$( angles$, term, ",") <>""
      angle  =val( word$( angles$, term, ","))
      sumSin = sumSin +sin( degRad( angle))
      sumCos = sumCos +cos( degRad( angle))
      term =term +1
   wend
   meanAngle= radDeg( atan2( sumSin, sumCos))
   if abs( sumSin) +abs( sumCos) <0.001 then notice "Not Available." +_
     chr$( 13) +"(" +angles$ +")" +_
     chr$( 13) +"Result nearly equals zero vector." +_
     chr$( 13) +"Displaying '666'.": meanAngle =666

end function

function degRad( theta)
    degRad =theta *Pi /180
end function

function radDeg( theta)
    radDeg =theta *180 /Pi
end function

function atan2( y, x)
    if x >0           then at =atn( y /x)
    if y >=0 and x <0 then at =atn( y /x) +pi
    if y <0  and x <0 then at =atn( y /x) -pi
    if y >0  and x =0 then at =    pi /2
    if y <0  and x =0 then at = 0 -pi /2
    if y =0  and x =0 then notice "undefined": end
    atan2 =at
end function
Output:
Mean Angle( "350,10") = 0.0 degrees.
Mean Angle( "90,180,270,360") = 666.0 degrees.
Mean Angle( "10,20,30") = 20.0 degrees.

to mean_angle :angles
   local "avgsin
   make "avgsin quotient apply "sum map "sin :angles count :angles
   local "avgcos
   make "avgcos quotient apply "sum map "cos :angles count :angles
   output (arctan :avgcos :avgsin)
end

foreach [[350 10] [90 180 270 360] [10 20 30]] [
  print (sentence [The average of \(] ? [\) is] (mean_angle ?))
]

bye
Output:
The average of ( 350 10 ) is 0
The average of ( 90 180 270 360 ) is 0
The average of ( 10 20 30 ) is 20

Lua

Translation of: Tcl
Works with: Lua version 5.1
function meanAngle (angleList)
  local sumSin, sumCos = 0, 0
  for i, angle in pairs(angleList) do
    sumSin = sumSin + math.sin(math.rad(angle))
    sumCos = sumCos + math.cos(math.rad(angle))
  end
  local result = math.deg(math.atan2(sumSin, sumCos))
  return string.format("%.2f", result)
end

print(meanAngle({350, 10}))
print(meanAngle({90, 180, 270, 360}))
print(meanAngle({10, 20, 30}))
Output:
-0.00
-90.00
20.00

Maple

The following procedure takes a list of numeric degrees (with attached units) such as

> [ 350, 10 ] *~ Unit(arcdeg);
                      [350 [arcdeg], 10 [arcdeg]]

as input. (We could use "degree" instead of "arcdeg", since "degree" is taken, by default, to mean angle measure, but it seems best to avoid the ambiguity.)

MeanAngle := proc( L )
        uses Units:-Standard; # for unit-awareness
        local   u;
        evalf( convert( argument( add( u, u = exp~( I *~ L ) ) ), 'units', 'radian', 'degree' ) )
end proc:

Applying this to the given data sets, we obtain:

> MeanAngle( [ 350, 10 ] *~ Unit(arcdeg) );
                                   0.

> MeanAngle( [ 90, 180, 270, 360 ] *~ Unit(arcdeg) );
                                   0.

> MeanAngle( [ 10, 20, 30 ] *~ Unit(arcdeg) );
                              20.00000000

Mathematica / Wolfram Language

meanAngle[data_List] := N@Arg[Mean[Exp[I data Degree]]]/Degree
Output:
meanAngle /@ {{350, 10}, {90, 180, 270, 360}, {10, 20, 30}}
{0., Interval[{-180., 180.}], 20.}

MATLAB / Octave

function u = mean_angle(phi)
	u = angle(mean(exp(i*pi*phi/180)))*180/pi;
end
 mean_angle([350, 10])
ans = -2.7452e-14
 mean_angle([90, 180, 270, 360])
ans = -90
 mean_angle([10, 20, 30])
ans =  20.000

MiniScript

atan2 = function(y, x)
	return 2 * atan((sqrt(x^2 + y^2) - x) / y)
end function

deg2rad = function(x); return x * pi / 180; end function
rad2deg = function(x); return x * 180 / pi; end function

meanAngle = function(angles)
	xsum = 0; ysum = 0
	for angle in angles
		xsum += cos(deg2rad(angle))
		ysum += sin(deg2rad(angle))
	end for
	return rad2deg(atan2(ysum / angles.len, xsum / angles.len))
end function

manyAngledOnes = [[350, 10], [90, 180, 270, 360], [10, 20, 30]]

for angles in manyAngledOnes
	mean = meanAngle(angles)
	print ["Mean of", angles, "is", mean].join(" ")
end for
Output:
Mean of [350, 10] is 0
Mean of [90, 180, 270, 360] is -90
Mean of [10, 20, 30] is 20.0

NetRexx

Translation of: C
/* NetRexx */
options replace format comments java crossref symbols nobinary
numeric digits 80

runSample(arg)
return

-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method getMeanAngle(angles) private static binary
  x_component = double 0.0
  y_component = double 0.0
  aK = int angles.words()
  loop a_ = 1 to aK
    angle_d = double angles.word(a_)
    angle_r = double Math.toRadians(angle_d)
    x_component = x_component + Math.cos(angle_r)
    y_component = y_component + Math.sin(angle_r)
    end a_
  x_component = x_component / aK
  y_component = y_component / aK
  avg_r = Math.atan2(y_component, x_component)
  avg_d = Math.toDegrees(avg_r)
  return avg_d

-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method runSample(arg) private static
  angleSet = [ '350 10', '90 180 270 360', '10 20 30', '370', '180' ]
  loop angles over angleSet
    say 'The mean angle of' angles.space(1, ',') 'is:'
    say '  'getMeanAngle(angles).format(6, 6)
    say
    end angles
  return
Output:
The mean angle of 350,10 is:
       0.000000

The mean angle of 90,180,270,360 is:
     -90.000000

The mean angle of 10,20,30 is:
      20.000000

The mean angle of 370 is:
      10.000000

The mean angle of 180 is:
     180.000000

Nim

Works with: Nim version 0.20.0+
import math, complex
 
proc meanAngle(deg: openArray[float]): float =
  var c: Complex[float]
  for d in deg:
    c += rect(1.0, degToRad(d))
  radToDeg(phase(c / float(deg.len)))
 
echo "The 1st mean angle is: ", meanAngle([350.0, 10.0]), " degrees"
echo "The 2nd mean angle is: ", meanAngle([90.0, 180.0, 270.0, 360.0]), " degrees"
echo "The 3rd mean angle is: ", meanAngle([10.0, 20.0, 30.0]), " degrees"

Output:

The 1st mean angle is: -1.614809932057922e-15 degrees
The 2nd mean angle is: -90.0 degrees
The 3rd mean angle is: 20.0 degrees

Oberon-2

Works with: oo2c
MODULE MeanAngle;
IMPORT
  M := LRealMath,
  Out;
CONST
  toRads = M.pi / 180;
  toDegs = 180 / M.pi;
VAR
  grades: ARRAY 64 OF LONGREAL;

PROCEDURE Mean(g: ARRAY OF LONGREAL): LONGREAL;
VAR
  i: INTEGER;
  sumSin, sumCos: LONGREAL;
BEGIN
  i := 0;sumSin := 0.0;sumCos := 0.0;
  WHILE g[i] # 0.0 DO
    sumSin := sumSin + M.sin(g[i] * toRads);
    sumCos := sumCos + M.cos(g[i] * toRads);  
    INC(i)
  END;
  RETURN M.arctan2(sumSin / i,sumCos / i);
END Mean;

BEGIN
  grades[0] := 350.0;grades[1] := 10.0;
  Out.LongRealFix(Mean(grades) * toDegs,15,9);Out.Ln;
  grades[0] := 90.0;grades[1] := 180.0;grades[2] := 270.0;grades[3] := 360.0;
  Out.LongRealFix(Mean(grades) * toDegs,15,9);Out.Ln;
  grades[0] := 10.0;grades[1] := 20.0;grades[2] := 30.0;grades[3] := 0.0;
  Out.LongRealFix(Mean(grades) * toDegs,15,9);Out.Ln; 
END MeanAngle.
Output:
   -0.000000000
  -90.000000000
   20.000000000

OCaml

let pi = 3.14159_26535_89793_23846_2643

let deg2rad d =
  d *. pi /. 180.0
 
let rad2deg r =
  r *. 180.0 /. pi

let mean_angle angles =
  let rad_angles = List.map deg2rad angles in
  let sum_sin = List.fold_left (fun sum a -> sum +. sin a) 0.0 rad_angles
  and sum_cos = List.fold_left (fun sum a -> sum +. cos a) 0.0 rad_angles
  in
  rad2deg (atan2 sum_sin sum_cos)

let test angles =
  Printf.printf "The mean angle of [%s] is: %g degrees\n"
    (String.concat "; " (List.map (Printf.sprintf "%g") angles))
    (mean_angle angles)

let () =
  test [350.0; 10.0];
  test [90.0; 180.0; 270.0; 360.0];
  test [10.0; 20.0; 30.0];
;;

or using the Complex module:

open Complex

let mean_angle angles =
  let sum =
    List.fold_left (fun sum a -> add sum (polar 1.0 (deg2rad a))) zero angles
  in
    rad2deg (arg sum)
Output:
The mean angle of [350; 10] is: -2.74518e-14 degrees
The mean angle of [90; 180; 270; 360] is: -90 degrees
The mean angle of [10; 20; 30] is: 20 degrees

ooRexx

Translation of: REXX
/*REXX program computes the  mean angle  (angles expressed in degrees). */
numeric digits 50                      /*use fifty digits of precision, */
       showDig=10                      /*··· but only display 10 digits.*/
xl = 350 10            ;      say showit(xl, meanAngleD(xl) )
xl = 90 180 270 360    ;      say showit(xl, meanAngleD(xl) )
xl = 10 20 30          ;      say showit(xl, meanAngleD(xl) )
exit                                   /*stick a fork in it, we're done.*/
/*----------------------------------MEANANGD subroutine-----------------*/
meanAngleD:  procedure;  parse arg xl;   numeric digits digits()+digits()%4
sum.=0
n=words(xl)
do j=1 to n
  sum.0sin+=rxCalcSin(word(xl,j))
  sum.0cos+=rxCalcCos(word(xl,j))
  End
If sum.0cos=0 Then
  Return sign(sum.0sin/n)*90
Else
  Return rxCalcArcTan((sum.0sin/n)/(sum.0cos/n))

showit: procedure expose showDig;  numeric digits showDig;  parse arg a,mA
        return left('angles='a,30)  'mean angle='  format(mA,,showDig,0)/1

::requires rxMath library;
Output:
angles=350 10                  mean angle= 0
angles=90 180 270 360          mean angle= 0
angles=10 20 30                mean angle= 20

PARI/GP

meanAngle(v)=atan(sum(i=1,#v,sin(v[i]))/sum(i=1,#v,cos(v[i])))%(2*Pi)
meanDegrees(v)=meanAngle(v*Pi/180)*180/Pi
apply(meanDegrees,[[350, 10], [90, 180, 270, 360], [10, 20, 30]])
Output:
[360.000000, 296.565051, 20.0000000]

Pascal

uses library math for sincos, a function of FPU80x87, atan2 and DegToRad. Tested with free pascal. Try to catch very small cos values and set to 0.0 degrees " Error : Not meaningful" as http://rosettacode.org/wiki/Averages/Mean_angle#Euler_Math_Toolbox complains.

program MeanAngle;
{$IFDEF DELPHI}
  {$APPTYPE CONSOLE}
{$ENDIF}
uses
  math;// sincos and atan2
type
  tAngles = array of double;

function MeanAngle(const a:tAngles;cnt:longInt):double;
// calculates mean angle.
// returns 0.0 if direction is not sure.
const
  eps = 1e-10;

var
  i : LongInt;
  s,c,
  Sumsin,SumCos : extended;
begin
  IF cnt = 0 then
  Begin
    MeanAngle := 0.0;
    EXIT;
  end;

  SumSin:= 0;
  SumCos:= 0;
  For i := Cnt-1 downto 0 do
  Begin
    sincos(DegToRad(a[i]),s,c);
    Sumsin := sumSin+s;
    SumCos := sumCos+c;
  end;
  s := SumSin/cnt;
  c := sumCos/cnt;
  IF c > eps then
    MeanAngle := RadToDeg(arctan2(s,c))
  else
    // Not meaningful
    MeanAngle := 0.0;
end;

Procedure OutMeanAngle(const a:tAngles;cnt:longInt);
var
  i : longInt;
Begin
  IF cnt > 0 then
  Begin
    write('The mean angle of [');
    For i := 0 to Cnt-2 do
      write(a[i]:0:2,',');
    write(a[Cnt-1]:0:2,'] => ');
    writeln(MeanAngle(a,cnt):0:16);
  end;
end;

var
  a:tAngles;
Begin
  setlength(a,4);

  a[0] := 350;a[1] := 10;
  OutMeanAngle(a,2);
  a[0] := 90;a[1] := 180;a[2] := 270;a[3] := 360;
  OutMeanAngle(a,4);
  a[0] := 10;a[1] := 20;a[2] := 30;
  OutMeanAngle(a,3);

  setlength(a,0);
end.
output
The mean angle of [350.00,10.00] => 0.0000000000000000
The mean angle of [90.00,180.00,270.00,360.00] => 0.0000000000000000
The mean angle of [10.00,20.00,30.00] => 20.0000000000000000

Perl

sub Pi () { 3.1415926535897932384626433832795028842 }

sub meanangle {
  my($x, $y) = (0,0);
  ($x,$y) = ($x + sin($_), $y + cos($_)) for @_;
  my $atan = atan2($x,$y);
  $atan += 2*Pi while $atan < 0;    # Ghetto fmod
  $atan -= 2*Pi while $atan > 2*Pi;
  $atan;
}

sub meandegrees {
  meanangle( map { $_ * Pi/180 } @_ ) * 180/Pi;
}

print "The mean angle of [@$_] is: ", meandegrees(@$_), " degrees\n"
  for ([350,10], [90,180,270,360], [10,20,30]);
Output:
The mean angle of [350 10] is: 360 degrees
The mean angle of [90 180 270 360] is: 270 degrees
The mean angle of [10 20 30] is: 20 degrees

Phix

Copied from Euphoria, and slightly improved

with javascript_semantics
function MeanAngle(sequence angles)
    atom x = 0, y = 0
    for i=1 to length(angles) do
        atom ai_rad = angles[i]*PI/180
        x += cos(ai_rad)
        y += sin(ai_rad)
    end for
    if abs(x)<1e-16 then return "not meaningful" end if
    return sprintf("%g",round(atan2(y,x)*180/PI,1e10))
end function
 
constant AngleLists = {{350,10},{90,180,270,360},{10,20,30},{180},{0,180}}
for i=1 to length(AngleLists) do
    sequence ai = AngleLists[i]
    printf(1,"%16V: Mean Angle is %s\n",{ai,MeanAngle(ai)})
end for
Output:
        {350,10}: Mean Angle is 0
{90,180,270,360}: Mean Angle is not meaningful
      {10,20,30}: Mean Angle is 20
           {180}: Mean Angle is 180
         {0,180}: Mean Angle is not meaningful

PHP

Translation of: C
<?php
$samples = array( 
	'1st' => array(350, 10),
	'2nd' => array(90, 180, 270, 360),
	'3rd' => array(10, 20, 30)
);

foreach($samples as $key => $sample){
	echo 'Mean angle for ' . $key . ' sample: ' . meanAngle($sample) . ' degrees.' . PHP_EOL;
} 

function meanAngle ($angles){
	$y_part = $x_part = 0;
	$size = count($angles);
	for ($i = 0; $i < $size; $i++){
		$x_part += cos(deg2rad($angles[$i]));
		$y_part += sin(deg2rad($angles[$i]));
	}
	$x_part /= $size;
	$y_part /= $size;
	return rad2deg(atan2($y_part, $x_part));
}
?>
Output:
Mean angle for 1st sample: -1.6148099320579E-15 degrees.
Mean angle for 2nd sample: -90 degrees.
Mean angle for 3rd sample: 20 degrees.

PicoLisp

(load "@lib/math.l")

(de meanAngle (Lst)
   (*/
      (atan2
         (sum '((A) (sin (*/ A pi 180.0))) Lst)
         (sum '((A) (cos (*/ A pi 180.0))) Lst) )
      180.0 pi ) )

(for L '((350.0 10.0) (90.0 180.0 270.0 360.0) (10.0 20.0 30.0))
   (prinl
      "The mean angle of ["
      (glue ", " (mapcar round L '(0 .)))
      "] is: " (round (meanAngle L))) )
Output:
The mean angle of [350, 10] is: 0.000
The mean angle of [90, 180, 270, 360] is: 90.000
The mean angle of [10, 20, 30] is: 20.000

PL/I

averages: procedure options (main);             /* 31 August 2012 */
   declare b1(2) fixed initial (350, 10);
   declare b2(4) fixed initial (90, 180, 270, 360);
   declare b3(3) fixed initial (10, 20, 30);

   put edit ( b1) (f(7));
   put edit ( ' mean=', mean(b1) )   (a, f(7) );
   put skip edit ( b3) (f(7));
   put edit ( ' mean=', mean(b3) )   (a, f(7) );
   put skip edit ( b2) (f(7));
   put edit ( ' mean=', mean(b2) )   (a, f(7) );

mean: procedure (a) returns (fixed);
   declare a(*) float (18);
   return ( atand(sum(sind(a))/hbound(a), sum(cosd(a))/hbound(a) ) );
end mean;

end averages;

Results (the final one brings up an error in inverse tangent):

    350     10 mean=      0
     10     20     30 mean=     20
     90    180    270    360 mean=
IBM0683I  ONCODE=1521  X or Y in ATAN(X,Y) or ATAND(X,Y) was invalid.
   At offset +000009CC in procedure with entry AVERAGES

PowerShell

function Get-MeanAngle ([double[]]$Angles)
{
    $x = ($Angles | ForEach-Object {[Math]::Cos($_ * [Math]::PI / 180)} | Measure-Object -Average).Average
    $y = ($Angles | ForEach-Object {[Math]::Sin($_ * [Math]::PI / 180)} | Measure-Object -Average).Average

    [Math]::Atan2($y, $x) * 180 / [Math]::PI
}
@(350, 10), @(90, 180, 270, 360), @(10, 20, 30) | ForEach-Object {Get-MeanAngle $_}
Output:
-2.74517688449847E-14
-90
20

Processing

void setup() {
  println(meanAngle(350, 10));
  println(meanAngle(90, 180, 270, 360));
  println(meanAngle(10, 20, 30));
}

float meanAngle(float... angles) {
  float sum1 = 0, sum2 = 0;
  for (int i = 0; i < angles.length; i++) {
    sum1 += sin(radians(angles[i])) / angles.length;
    sum2 += cos(radians(angles[i])) / angles.length;
  }
  return degrees(atan2(sum1, sum2));
}
Output:
-7.8025005E-6
90.0
20.0

PureBasic

NewList angle.d()

Macro AE(x)
  AddElement(angle()) : angle()=x
EndMacro

Procedure.d atan3(y.d,x.d)
  If x<=0.0 : ProcedureReturn Sign(y)*#PI/2 : EndIf
  If x>0.0  : ProcedureReturn ATan(y/x)     : EndIf
  If y>0.0  : ProcedureReturn ATan(y/x)+#PI : EndIf
  ProcedureReturn ATan(y/x)-#PI
EndProcedure

Procedure.d mAngle(List angle.d())
  Define.d sumS,sumC
  ForEach angle()    
    sumS+Sin(Radian(angle())) : sumC+Cos(Radian(angle()))    
  Next
  ProcedureReturn Degree(atan3(sumS,sumC))
EndProcedure

AE(350.0) : AE(10.0)
Debug StrD(mAngle(angle()),6) : ClearList(angle())

AE(90.0) : AE(180.0) : AE(270.0) : AE(360.0)
Debug StrD(mAngle(angle()),6) : ClearList(angle())

AE(10.0) : AE(20.0) : AE(30.0)
Debug StrD(mAngle(angle()),6) : ClearList(angle())
Output:
-0.000000
-90.000000
20.000000

Python

Works with: Python version 2.6+
>>> from cmath import rect, phase
>>> from math import radians, degrees
>>> def mean_angle(deg):
...     return degrees(phase(sum(rect(1, radians(d)) for d in deg)/len(deg)))
... 
>>> for angles in [[350, 10], [90, 180, 270, 360], [10, 20, 30]]:
...     print('The mean angle of', angles, 'is:', round(mean_angle(angles), 12), 'degrees')
...     
The mean angle of [350, 10] is: -0.0 degrees
The mean angle of [90, 180, 270, 360] is: -90.0 degrees
The mean angle of [10, 20, 30] is: 20.0 degrees
>>>

R

deg2rad <- function(x) {
  x * pi/180
}

rad2deg <- function(x) {
  x * 180/pi
}

deg2vec <- function(x) {
  c(sin(deg2rad(x)), cos(deg2rad(x)))
}

vec2deg <- function(x) {
  res <- rad2deg(atan2(x[1], x[2]))
  if (res < 0) {
    360 + res
  } else {
    res
  }
}

mean_vec <- function(x) {
  y <- lapply(x, deg2vec)
  Reduce(`+`, y)/length(y)
}

mean_deg <- function(x) {
  vec2deg(mean_vec(x))
}

mean_deg(c(350, 10))
mean_deg(c(90, 180, 270, 360))
mean_deg(c(10, 20, 30))
Output:
360
270
20

Racket

The formula given above can be straightforwardly transcribed into a program:

#lang racket

(define (mean-angle αs)
  (radians->degrees
   (mean-angle/radians
    (map degrees->radians αs))))

(define (mean-angle/radians αs)
  (define n (length αs))
  (atan (* (/ 1 n) (for/sum ([α_j αs]) (sin α_j)))
        (* (/ 1 n) (for/sum ([α_j αs]) (cos α_j)))))

(mean-angle '(350 0 10))
(mean-angle '(90 180 270 360))
(mean-angle '(10 20 30))
Output:
-1.0710324872062297e-15
-90.0
19.999999999999996

Raku

(formerly Perl 6)

Works with: Rakudo version 2015.12

This solution refuses to return an answer when the angles cancel out to a tiny magnitude.

# Of course, you can still use pi and 180.
sub deg2rad { $^d * tau / 360 }
sub rad2deg { $^r * 360 / tau }

sub phase ($c)  {
    my ($mag,$ang) = $c.polar;
    return NaN if $mag < 1e-16;
    $ang;
}

sub meanAngle { rad2deg phase [+] map { cis deg2rad $_ }, @^angles }

say meanAngle($_).fmt("%.2f\tis the mean angle of "), $_ for
    [350, 10],
    [90, 180, 270, 360],
    [10, 20, 30];
Output:
-0.00	is the mean angle of 350 10
NaN	is the mean angle of 90 180 270 360
20.00	is the mean angle of 10 20 30

REXX

This REXX version uses an   ATAN2   solution.

The REXX language doesn't have most of the higher mathematical functions (like sqrt), and none of the trigonometric
functions,   so all of them have to be included as RYO   (Roll-Your-Own).

Note that the second set of angles:    90    180   270   360

is the same as:                        90    180   -90     0
           and:                      -270   -180   -90  -360

and other combinations.

All the trigonometric functions use normalization   (converting the angle to a unit circle)   before computation,   and most
of them use shortcuts for some exact values,   so there is a minimum of errors due to rounding for   near values   for some
common values.

The consequence is the trig functions may return exact values such as   0   (zero)   for   sin(-2)   instead of   -8.154E-61.

This very small difference (almost inconsequential) makes a significant difference when that value is used for a parameter
for the   ATAN2   function;   in particular, the   sign   of the value.

There isn't much difference between:

           -8.154e-61   and
           +8.154e-61

in magnitude, but the   ATAN2   function treats those two numbers very differently as the angle will be in different quadrants,
thereby yielding a different value.

Usually this just results in an angle of   -90º   instead of   +270º   (both angles are equivalent).

Also note that the REXX subroutines are largely not commented as they provide a support structure that's normally present
in other computer programming languages as BIFs   (Built-In-Functions);   to add comments and expand the REXX statements
into single lines would increase the program's bulk and detract from the main program.

/*REXX program  computes  the   mean angle   for a  group of angles  (expressed in degrees). */
call pi                                          /*define the value of  pi  to some accuracy.*/
numeric digits length(pi) - 1;                   /*use PI width  decimal digits of precision,*/
        showDig= 10                              /*only display  ten  decimal digits.        */
#= 350 10         ;   say show(#, meanAngleD(#)) /*display mean angle (in degrees), 1st case.*/
#= 90 180 270 360 ;   say show(#, meanAngleD(#)) /*   "      "    "     "    "      2nd   "  */
#= 10 20 30       ;   say show(#, meanAngleD(#)) /*   "      "    "     "    "      3rd   "  */
exit                                             /*stick a fork in it, we're all done with it*/
/*───────────────────────────────────────────────────────────────────────────────────────────*/
.sinCos: arg z,_,i; x=x*x;  do k=2 by 2 until p=z; p=z; _=-_*x/(k*(k+i)); z=z+_; end;  return z
$fuzz:  return  min(arg(1), max(1, digits() - arg(2) ) )
Acos:   procedure; parse arg x;        return pi() * .5 - Asin(x)
Atan:   parse arg x; if abs(x)=1  then return pi()*.25 * sign(x);  return Asin(x/sqrt(1 + x*x))
d2d:    return arg(1)           //  360
d2r:    return r2r(d2d(arg(1))  /   180   * pi() )
r2d:    return d2d((r2r(arg(1)) /   pi()) * 180)
r2r:    return arg(1)           // (pi()  *   2)
pi: pi=3.1415926535897932384626433832795028841971693993751058209749445923078164062862;return pi
/*───────────────────────────────────────────────────────────────────────────────────────────*/
Asin:   procedure;  parse arg x 1 z 1 o 1 p;          a= abs(x);                aa= a * a
        if a>1  then call AsinErr x                            /*argument X  is out of range.*/
        if a >= sqrt(2) * .5  then  return sign(x) * acos( sqrt(1 - aa),  '-ASIN')
          do j=2  by 2  until p=z;  p= z;  o= o * aa * (j-1) / j;   z= z +o / (j+1);   end
        return  z                                              /* [↑]  compute until no noise*/
/*───────────────────────────────────────────────────────────────────────────────────────────*/
Atan2:  procedure; parse arg y,x;                     call pi;        s= sign(y)
          select
          when x=0  then  z= s * pi * .5
          when x<0  then  if  y=0  then z= pi;  else z= s * (pi - abs( Atan(y/x) ) )
          otherwise       z= s * Atan(y / x)
          end   /*select*/;                           return z
/*───────────────────────────────────────────────────────────────────────────────────────────*/
cos:    procedure; parse arg x;      x= r2r(x);       numeric fuzz  $fuzz(6, 3)
        a= abs(x);      if a=0  then return   1;      if a=pi    then return -1
        if a=pi*.5 | a= pi*1.5  then return   0;      if a=pi/3  then return .5
                  if a= pi*2/3  then return -.5;                      return .sinCos(1, 1, -1)
/*───────────────────────────────────────────────────────────────────────────────────────────*/
meanAngleD: procedure;  parse arg x;                  numeric digits digits() + digits() % 4
            n= words(x);                              _sin= 0;              _cos= 0
               do j=1  for n;  != d2r( word(x, j));   _sin= _sin + sin(!);  _cos= _cos + cos(!)
               end   /*j*/
            return  r2d( Atan2( _sin/n, _cos/n) )
/*───────────────────────────────────────────────────────────────────────────────────────────*/
show:   parse arg a,mA;                               _= format(ma, , showDig, 0) / 1
        return left('angles='a, 30)   "mean angle="   right(_, max(4, length(_) ) )
/*───────────────────────────────────────────────────────────────────────────────────────────*/
sin:    procedure; parse arg x;   x= r2r(x);          numeric fuzz  $fuzz(5, 3)
        if x=pi * .5         then return 1;           if x==pi * 1.5  then return -1
        if abs(x)=pi | x=0   then return 0;           return .sinCos(x, x, +1)
/*───────────────────────────────────────────────────────────────────────────────────────────*/
sqrt:   procedure; parse arg x; if x=0  then return 0;  d=digits();  m.=9; numeric form; h= d+6
        numeric digits;  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
output   when using the default internal inputs:
angles=350 10                  mean angle=    0
angles=90 180 270 360          mean angle=  -90
angles=10 20 30                mean angle=   20

Note that with the increase in decimal digit precision, the 2nd mean angle changed dramatically from an earlier result.

Ring

# Project : Averages/Mean angle

load "stdlib.ring"
decimals(6)
pi = 3.1415926535897
angles = [350,10]
see meanangle(angles, len(angles)) + nl
angles = [90,180,270,360]
see meanangle(angles, len(angles)) + nl
angles = [10,20,30]
see meanangle(angles, len(angles)) + nl
  
func meanangle(angles, n)
        sumsin = 0
        sumcos = 0
        for i = 1 to n
             sumsin = sumsin + sin(angles[i]*pi/180)
             sumcos = sumcos + cos(angles[i]*pi/180)
        next
        return 180/pi*atan3(sumsin, sumcos)
 
func atan3(y,x)
        if x <= 0
           return sign(y)*pi/2
        ok
        if x>0
           return atan(y/x)
        else
           if y>0 
              return atan(y/x)+pi
           else 
              return atan(y/x)-pi
           ok
        ok

Output:

-0.000000
-90
20.000000

RPL

≪ DEG → angles
  ≪  0 1 angles SIZE FOR j
        1 angles j GET R→C P→R + NEXT
      angles SIZE / ARG      
≫ ≫ 'MEANG' STO 
Input:
{ 350 10 } MEANG
{ 90 180 270 360 } MEANG
{ 10 20 30 } MEANG
Output:
3: 0
2: -90
1: 20

Ruby

require 'complex' # Superfluous in Ruby >= 2.0; complex is added to core.

def deg2rad(d)
  d * Math::PI / 180
end
 
def rad2deg(r)
  r * 180 / Math::PI
end

def mean_angle(deg)
  rad2deg((deg.inject(0) {|z, d| z + Complex.polar(1, deg2rad(d))} / deg.length).arg)
end

[[350, 10], [90, 180, 270, 360], [10, 20, 30]].each {|angles|
  puts "The mean angle of %p is: %f degrees" % [angles, mean_angle(angles)]
}
Output:
The mean angle of [350, 10] is: -0.000000 degrees
The mean angle of [90, 180, 270, 360] is: -90.000000 degrees
The mean angle of [10, 20, 30] is: 20.000000 degrees

Rust

use std::f64;
// the macro is from
// http://stackoverflow.com/questions/30856285/assert-eq-with-floating-
// point-numbers-and-delta
fn mean_angle(angles: &[f64]) -> f64 {
    let length: f64 = angles.len() as f64;
    let cos_mean: f64 = angles.iter().fold(0.0, |sum, i| sum + i.to_radians().cos()) / length;
    let sin_mean: f64 = angles.iter().fold(0.0, |sum, i| sum + i.to_radians().sin()) / length;
    (sin_mean).atan2(cos_mean).to_degrees()
}

fn main() {
    let angles1 = [350.0_f64, 10.0];
    let angles2 = [90.0_f64, 180.0, 270.0, 360.0];
    let angles3 = [10.0_f64, 20.0, 30.0];
    println!("Mean Angle for {:?}  is {:.5} degrees",
             &angles1,
             mean_angle(&angles1));
    println!("Mean Angle for {:?}  is {:.5} degrees",
             &angles2,
             mean_angle(&angles2));
    println!("Mean Angle for {:?}  is {:.5} degrees",
             &angles3,
             mean_angle(&angles3));
}

macro_rules! assert_diff{
    ($x: expr,$y : expr, $diff :expr)=>{
        if ( $x - $y ).abs() > $diff {
            panic!("floating point difference is to big {}", $x - $y );
        }
    }
}

#[test]
fn calculate() {
    let angles1 = [350.0_f64, 10.0];
    let angles2 = [90.0_f64, 180.0, 270.0, 360.0];
    let angles3 = [10.0_f64, 20.0, 30.0];
    assert_diff!(0.0, mean_angle(&angles1), 0.001);
    assert_diff!(-90.0, mean_angle(&angles2), 0.001);
    assert_diff!(20.0, mean_angle(&angles3), 0.001);
}

Scala

Library: Scala
trait MeanAnglesComputation {
  import scala.math.{Pi, atan2, cos, sin}

  def meanAngle(angles: List[Double], convFactor: Double = 180.0 / Pi) = {
    val sums = angles.foldLeft((.0, .0))((r, c) => {
      val rads = c / convFactor
      (r._1 + sin(rads), r._2 + cos(rads))
    })
    val result = atan2(sums._1, sums._2)
    (result + (if (result.signum == -1) 2 * Pi else 0.0)) * convFactor
  }
}

object MeanAngles extends App with MeanAnglesComputation {
  assert(meanAngle(List(350, 10), 180.0 / math.Pi).round == 360, "Unexpected result with 350, 10")
  assert(meanAngle(List(90, 180, 270, 360)).round == 270, "Unexpected result with 90, 180, 270, 360")
  assert(meanAngle(List(10, 20, 30)).round == 20, "Unexpected result with 10, 20, 30")
  println("Successfully completed without errors.")
}

Scheme

Translation of: Common Lisp
(import (srfi 1 lists))  ;; use 'fold' from library

(define (average l)
  (/ (fold + 0 l) (length l)))

(define pi 3.14159265358979323846264338327950288419716939937510582097) 

(define (radians a)
  (* pi 1/180 a))

(define (degrees a)
  (* 180 (/ 1 pi) a))

(define (mean-angle angles)
  (let* ((angles (map radians angles))
         (cosines (map cos angles))
         (sines (map sin angles)))
    (degrees (atan (average sines) (average cosines)))))

(for-each (lambda (angles)
            (display "The mean angle of ") (display angles) 
            (display " is ") (display (mean-angle angles)) (newline))
          '((350 10) (90 180 270 360) (10 20 30)))
The mean angle of (350 10) is -1.614809932057922E-15
The mean angle of (90 180 270 360) is -90.0
The mean angle of (10 20 30) is 19.999999999999996

Seed7

$ include "seed7_05.s7i";
  include "float.s7i";
  include "math.s7i";
  include "complex.s7i";

const func float: deg2rad (in float: degree) is
  return degree * PI / 180.0;

const func float: rad2deg (in float: rad) is
  return rad * 180.0 / PI;

const func float: meanAngle (in array float: degrees) is func
  result
    var float: mean is 0.0;
  local
    var float: degree is 0.0;
    var complex: sum is complex.value;
  begin
    for degree range degrees do
      sum +:= polar(1.0, deg2rad(degree));
    end for;
    mean := rad2deg(arg(sum / complex conv length(degrees)));
  end func;

const proc: main is func
  begin
    writeln(meanAngle([] (350.0, 10.0)) digits 4);
    writeln(meanAngle([] (90.0, 180.0, 270.0, 360.0)) digits 4);
    writeln(meanAngle([] (10.0, 20.0, 30.0)) digits 4);
  end func;
Output:
0.0000
90.0000
20.0000

Sidef

func mean_angle(angles) {
    atan2(
        Math.avg(angles.map{ .deg2rad.sin }...),
        Math.avg(angles.map{ .deg2rad.cos }...),
    ) -> rad2deg
}

[[350,10], [90,180,270,360], [10,20,30]].each { |angles|
  say "The mean angle of #{angles.dump} is: #{ '%.2f' % mean_angle(angles)} degrees"
}
Output:
The mean angle of [350, 10] is: 0.00 degrees
The mean angle of [90, 180, 270, 360] is: -90.00 degrees
The mean angle of [10, 20, 30] is: 20.00 degrees

Stata

mata
function meanangle(a) {
	return(arg(sum(exp(C(0,a)))))
}

deg=pi()/180

meanangle((350,10)*deg)/deg
  -1.61481e-15
meanangle((90,180,270,360)*deg)/deg
  0
meanangle((10,20,30)*deg)/deg
  20
end

Swift

import Foundation

@inlinable public func d2r<T: FloatingPoint>(_ f: T) -> T { f * .pi / 180 }
@inlinable public func r2d<T: FloatingPoint>(_ f: T) -> T { f * 180 / .pi }

public func meanOfAngles(_ angles: [Double]) -> Double {
  let cInv = 1 / Double(angles.count)
  let (s, c) =
    angles.lazy
      .map(d2r)
      .map({ (sin($0), cos($0)) })
      .reduce(into: (0.0, 0.0), { $0.0 += $1.0; $0.1 += $1.1 })

  return r2d(atan2(cInv * s, cInv * c))
}

let fmt = { String(format: "%lf", $0) }

print("Mean of angles (350, 10) => \(fmt(meanOfAngles([350, 10])))")
print("Mean of angles (90, 180, 270, 360) => \(fmt(meanOfAngles([90, 180, 270, 360])))")
print("Mean of angles (10, 20, 30) => \(fmt(meanOfAngles([10, 20, 30])))")
Output:
Mean of angles (350, 10) => -0.000000
Mean of angles (90, 180, 270, 360) => -90.000000
Mean of angles (10, 20, 30) => 20.000000

Tcl

proc meanAngle {angles} {
    set toRadians [expr {atan2(0,-1) / 180}]
    set sumSin [set sumCos 0.0]
    foreach a $angles {
	set sumSin [expr {$sumSin + sin($a * $toRadians)}]
	set sumCos [expr {$sumCos + cos($a * $toRadians)}]
    }
    # Don't need to divide by counts; atan2() cancels that out
    return [expr {atan2($sumSin, $sumCos) / $toRadians}]
}

Demonstration code:

# A little pretty-printer
proc printMeanAngle {angles} {
    puts [format "mean angle of \[%s\] = %.2f" \
	      [join $angles ", "] [meanAngle $angles]]
}

printMeanAngle {350 10}
printMeanAngle {90 180 270 360}
printMeanAngle {10 20 30}
Output:
mean angle of [350, 10] = -0.00
mean angle of [90, 180, 270, 360] = -90.00
mean angle of [10, 20, 30] = 20.00

Vala

double meanAngle(double[] angles) {
  double y_part = 0.0;
  double x_part = 0.0;
  
  for (int i = 0; i < angles.length; i++) {
    x_part += Math.cos(angles[i] * Math.PI / 180.0);
    y_part += Math.sin(angles[i] * Math.PI / 180.0);
  }

  return Math.atan2(y_part / angles.length, x_part / angles.length) * 180 / Math.PI;
}

void main() {
  double[] angleSet1 = {350.0, 10.0};
  double[] angleSet2 = {90.0, 180.0, 270.0, 360.0};
  double[] angleSet3 = {10.0, 20.0, 30.0};

  print("\nMean Angle for 1st set :  %lf degrees", meanAngle(angleSet1));
  print("\nMean Angle for 2nd set : %lf degrees", meanAngle(angleSet2));
  print("\nMean Angle for 3rd set :  %lf degrees\n", meanAngle(angleSet3));
}
Output:
Mean Angle for 1st set :  -0.000000 degrees
Mean Angle for 2nd set : -90.000000 degrees
Mean Angle for 3rd set :  20.000000 degrees

VBA

Option Base 1
Private Function mean_angle(angles As Variant) As Double
    Dim sins() As Double, coss() As Double
    ReDim sins(UBound(angles))
    ReDim coss(UBound(angles))
    For i = LBound(angles) To UBound(angles)
        sins(i) = Sin(WorksheetFunction.Radians(angles(i)))
        coss(i) = Cos(WorksheetFunction.Radians(angles(i)))
    Next i
    mean_angle = WorksheetFunction.Degrees( _
        WorksheetFunction.Atan2( _
        WorksheetFunction.sum(coss), _
        WorksheetFunction.sum(sins)))
End Function
Public Sub main()
    Debug.Print Format(mean_angle([{350,10}]), "##0")
    Debug.Print Format(mean_angle([{90, 180, 270, 360}]), "##0")
    Debug.Print Format(mean_angle([{10, 20, 30}]), "##0")
End Sub
Output:
0
-90
20

Visual Basic .NET

Translation of: C#
Imports System.Math

Module Module1

    Function MeanAngle(angles As Double()) As Double
        Dim x = angles.Sum(Function(a) Cos(a * PI / 180)) / angles.Length
        Dim y = angles.Sum(Function(a) Sin(a * PI / 180)) / angles.Length
        Return Atan2(y, x) * 180 / PI
    End Function

    Sub Main()
        Dim printMean = Sub(x As Double()) Console.WriteLine("{0:0.###}", MeanAngle(x))
        printMean({350, 10})
        printMean({90, 180, 270, 360})
        printMean({10, 20, 30})
    End Sub

End Module
Output:
0
-90
20

V (Vlang)

Translation of: go
import math
 
fn mean_angle(deg []f64) f64 {
	mut ss, mut sc := f64(0), f64(0)
	for x in deg {
		s, c := math.sincos(x * math.pi / 180)
		ss += s
		sc += c
	}
	return math.atan2(ss, sc) * 180 / math.pi
}
 
fn main() {
	for angles in [
		[f64(350), 10],
		[f64(90), 180, 270, 360],
		[f64(10), 20, 30],
	] {
		println("The mean angle of $angles is: ${mean_angle(angles)} degrees")
	}
}
Output:
The mean angle of [350, 10] is: -2.6644363878955713e-14 degrees
The mean angle of [90, 180, 270, 360] is: -90 degrees
The mean angle of [10, 20, 30] is: 19.999999999999996 degree

Wren

Library: Wren-fmt
import "./fmt" for Fmt

var meanAngle = Fn.new { |angles|
    var n = angles.count
    var sinSum = 0
    var cosSum = 0
    for (angle in angles) {
        sinSum = sinSum + (angle * Num.pi / 180).sin
        cosSum = cosSum + (angle * Num.pi / 180).cos
    }
    return (sinSum/n).atan(cosSum/n) * 180 / Num.pi
}

var angles1 = [350, 10]
var angles2 = [90, 180, 270, 360]
var angles3 = [10, 20, 30]

var i = 1
for (angles in [angles1, angles2, angles3]) {
    System.print("Mean for angles %(i) is : %(Fmt.f(6, meanAngle.call(angles), 2))")
    i = i + 1
}
Output:
Mean for angles 1 is :  -0.00
Mean for angles 2 is : -90.00
Mean for angles 3 is :  20.00

XPL0

include c:\cxpl\codes;

def Pi  = 3.14159265358979323846;
def D2R = Pi/180.0;             \coefficient to convert degrees to radians

func real MeanAng(A);           \Return the mean of the given list of angles
int  A;
real X, Y;
int  I;
[X:= 0.0;  Y:= 0.0;
for I:= 1 to A(0) do
    [X:= X + Cos(D2R*float(A(I)));
     Y:= Y + Sin(D2R*float(A(I)));
    ];
return ATan2(Y,X)/D2R;
];

[Format(5, 15);
RlOut(0, MeanAng([2, 350, 10]));  CrLf(0);
RlOut(0, MeanAng([4, 90, 180, 270, 360]));  CrLf(0);
RlOut(0, MeanAng([3, 10, 20, 30]));  CrLf(0);
]
Output:
   -0.000000000000003
  -90.000000000000000
   20.000000000000000

The second example is interesting because it computes ATan2(0.,0.), which is undefined in mathematics (like division by zero), but the floating point processor in IBM-PC-type computers defines it as zero. The reason -90 gets displayed instead is due to small rounding errors (and another extra-mathematical concept, -0). In fact almost any angle can result because of slight rounding errors as Y and X both approach zero.

zkl

fcn meanA(a1,a2,etc){ 
   as:=vm.arglist.pump(List,"toFloat","toRad");
   n:=as.len();
   (as.apply("sin").sum(0.0)/n)
   .atan2(as.apply("cos").sum(0.0)/n)
   .toDeg()
}
Output:
zkl: meanA(350,10)
-1.61481e-15
zkl: meanA(90,180,270,360)
-90
meanA(10,20,30)
20