Add all the A tasks

This commit is contained in:
Ingy döt Net 2013-04-10 14:58:50 -07:00
parent 2dd7375f96
commit 051504d65b
1608 changed files with 18584 additions and 0 deletions

View file

@ -0,0 +1,23 @@
When calculating the [[wp:Mean of circular quantities|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:
# Assume all angles are on the unit circle and convert them to complex numbers expressed in real and imaginary form.
# 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.
(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
::<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.
;See Also
* [[Averages/Mean time of day]]

View file

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

View file

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

View file

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

View file

@ -0,0 +1,6 @@
import Data.Complex (cis, phase)
meanAngle = (/ pi) . (* 180) . phase . sum . map (cis . (/ 180) . (* pi))
main = mapM_ (\angles -> putStrLn $ "The mean angle of " ++ show angles ++ " is: " ++ show (meanAngle angles) ++ " degrees")
[[350, 10], [90, 180, 270, 360], [10, 20, 30]]

View file

@ -0,0 +1,14 @@
(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))) )

View file

@ -0,0 +1,12 @@
>>> 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
>>>

View file

@ -0,0 +1,57 @@
/*REXX program to compute the mean angle (angles expressed in degrees).*/
numeric digits 50 /*use fifty digits of precision. */
showDigs=10 /* ... but only show ten 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 done.*/
/*──────────────────────────────────MEANANGD subroutine─────────────────*/
meanAngleD: procedure; arg x; _sin=0; _cos=0
numeric digits $d()+$d()%4
n=words(x); do j=1 for n
xr = d2r(d2d(word(x,j)))
_sin = _sin + sin(xr)
_cos = _cos + cos(xr)
end /*j*/
return r2d(atan2(_sin/n, _cos/n))
/*═════════════════════════════general 1-line subs══════════════════════*/
/*The 1-line subs were broken up into multiple lines for easier reading.*/
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)//(2*pi())
p: return word(arg(1),1)
$d: return p(arg(1) digits())
$fuzz: return min(arg(1),max(1,$d()-arg(2)))
showit: procedure expose showDigs; numeric digits showDigs; arg a,ma
return left('angles='a,30) 'mean angle=' format(ma,,showDigs,0)/1
acos: procedure; arg x; if x<-1 | x>1 then call $81r -1,1,x,"ACOS"
return .5*pi() - asin(x) /* $81r subroutine not included here.*/
atan: if abs(arg(1))=1 then return pi()*.25*sign(arg(1))
return asin(arg(1) / sqrt(1+arg(1)**2))
asin: procedure; arg x; if x<-1 | x>1 then call $81r -1,1,x,"ASIN"
s=x*x; if abs(x)>=.7 then return sign(x)*acos(sqrt(1-s),'-ASIN')
z=x; o=x; p=z; do j=2 by 2; o=o*s*(j-1)/j; z=z+o/(j+1)
if z=p then leave; p=z; end; return z
atan2: procedure; arg y,x; pi=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; return z
cos: procedure; arg x; x=r2r(x); a=abs(x); numeric fuzz $fuzz(5,3)
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=2*pi()/3 then return -.5; return .sincos(1,1,-1)
sin: procedure; 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)
.sincos: parse arg z,_,i; x=x*x; p=z; do k=2 by 2; _=-_*x/(k*(k+i)); z=z+_
if z=p then leave; p=z; end; return z
sqrt: procedure; parse arg x; if x=0 then return 0; d=digits()
numeric digits 11; g=.sqrtGuess(); do j=0 while p>9;m.j=p; p=p%2+1
end; do k=j+5 to 0 by -1; if m.k>11 then numeric digits m.k
g=.5*(g+x/g); end; numeric digits d; return g/1
.sqrtGuess: if x<0 then call er 02,x p($.ff 'SQRT') "negative"
/*The above IF statement was left here to show checking for x<0.*/
numeric form; m.=11; p=d+d%4+2
parse value format(x,2,1,,0) 'E0' with g 'E' _ .;return g*.5'E'_%2
pi: return ,
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148

View file

@ -0,0 +1,15 @@
#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))

View file

@ -0,0 +1,17 @@
require 'complex'
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)]
}

View file

@ -0,0 +1,10 @@
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}]
}

View file

@ -0,0 +1,9 @@
# 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}