2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -7,17 +7,26 @@ To calculate the mean angle of several angles:
# Compute the mean of the complex numbers.
# Convert the complex mean to polar coordinates whereupon the phase of the complex mean is the required angular mean.
<br>
(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 <math>\alpha_1,\dots,\alpha_n</math> the mean is computed by
: Given the angles <math>\alpha_1,\dots,\alpha_n</math> the mean is computed by
::<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>
The task is to:
# 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).
# Use the function to compute the means of these lists of angles (in degrees): [350, 10], [90, 180, 270, 360], [10, 20, 30]; and show your output here.
{{task heading}}
;See Also
* [[Averages/Mean time of day]]
# 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).
# Use the function to compute the means of these lists of angles (in degrees):
#* &nbsp; [350, 10]
#* &nbsp; [90, 180, 270, 360]
#* &nbsp; [10, 20, 30]
# Show your output here.
{{task heading|See also}}
{{Related tasks/Statistical measures}}
<br><hr>

View file

@ -0,0 +1,26 @@
#!/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)))
)

View file

@ -0,0 +1,27 @@
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;
}

View file

@ -0,0 +1,21 @@
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])

View file

@ -1,5 +1,7 @@
sub deg2rad { $^d * pi / 180 }
sub rad2deg { $^r * 180 / pi }
# 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;

View file

@ -1,57 +1,54 @@
/*REXX program computes the mean angle (the angles expressed in degrees). */
numeric digits 50 /*use 50 decimal digits of precision,*/
showDig=10 /* but only display ten decimal digits.*/
# = 350 10 ; say showit(#, meanAngleD(#) )
# = 90 180 270 360 ; say showit(#, meanAngleD(#) )
# = 10 20 30 ; say showit(#, meanAngleD(#) )
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────subroutines──────────────────────────────────────────────*/
/*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; showDig=10 /*use PI width decimal digits of precision,*/
/* but only display 10 decimal digits. */
#=350 10 ; say show(#, meanAngleD(#) )
#=90 180 270 360 ; say show(#, meanAngleD(#) )
#=10 20 30 ; say show(#, meanAngleD(#) )
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))
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)
r2r: return arg(1) // (pi() * 2)
p: return word(arg(1), 1)
pi: pi=3.1415926535897932384626433832795028841971693993751058209749445923078164062862;return pi
asin: procedure; parse arg x 1 z 1 o 1 p; xx=x*x
if xx>=.5 then return sign(x) * acos(sqrt(1-xx))
do j=2 by 2 until p=z; p=z; o=o*xx*(j-1)/j; z=z+o/(j+1); end
return z /* [↑] compute until no more noise. */
Asin: procedure; parse arg x 1 z 1 o 1 p; xx=x*x
if xx>=.5 then return sign(x) * Acos(sqrt(1-xx))
do j=2 by 2 until p=z; p=z; o=o*xx*(j-1)/j; z=z+o/(j+1); end /*j*/
return z /* [↑] compute until no more noise.*/
atan2: procedure; parse arg y,x; call pi; s=sign(y)
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)
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)
if a=pi*2/3 then return -.5; return .sinCos(1, 1, -1)
meanAngleD: procedure; parse arg x; numeric digits digits()+digits()%4
_sin=0; _cos=0; n=words(x); do j=1 for n; !=d2r(word(x,j))
_sin=_sin + sin(!)
_cos=_cos + cos(!)
end /*j*/
return r2d(atan2(_sin/n, _cos/n))
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))
showit: procedure expose showDig; numeric digits showDig; parse arg a,mA
return left('angles='a,30) 'mean angle=' 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(_)))
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(); i=; m.=9
numeric digits 9; numeric form; h=d+6; if x<0 then do; x=-x; i='i'; end
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*/
numeric digits d; return (g/1)i /*make complex if X < 0.*/
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

View file

@ -0,0 +1,43 @@
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);
}