0

I have a set of angles A with every a in A = [0, 360). Now I want to calculate the mean angle A.

I found a solution on rosettacode.org:

public static void main(String[] args) {
    printAverageAngle(350.0, 10.0);
    printAverageAngle(0.0, 180);
    printAverageAngle(0.0, 180.0, 180.0);
    printAverageAngle(0.0, 0.0, 180.0);
    printAverageAngle(0.0, 0.0, 180.0, 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);
}

But there are some unwanted solutions.

The mean angle of [350.0, 10.0] is -1.614809932057922E-15 // good

The mean angle of [0.0, 180.0] is 90.0 // good

The mean angle of [0.0, 180.0, 180.0] is 180.0 // bad

The mean angle of [0.0, 0.0, 180.0] is 7.016709298534877E-15 // bad

The mean angle of [0.0, 0.0, 180.0, 180.0] is 90.0 // good

In my opinion the mean angle of [0.0, 180.0, 180.0] should be 120 and of [0.0, 0.0, 180.0] it should be 60.

Has anyone a method that works with these special cases? Or an idea to fix it?

Thanks

Daniel
  • 29
  • 2
  • 4
    what's wrong with regular arithmetic average ? – c0der Sep 17 '17 at 16:10
  • 2
    Possible duplicate of [How do you calculate the average of a set of circular data?](https://stackoverflow.com/questions/491738/how-do-you-calculate-the-average-of-a-set-of-circular-data) – Frank Puffer Sep 17 '17 at 16:10
  • @coder Imagine a pair of angles being at 5 and 355 degrees. You would expect their mean to be 0 but the answer would be 180. – meowgoesthedog Sep 17 '17 at 17:21
  • No. I expect the average to be 180. The average bearing is 0 – c0der Sep 17 '17 at 17:29

1 Answers1

0

One approach is to modify the iterative approach to finding means, that is, in C:

Mean = 0.0
Count = 0;
for ( i=0; i<N; ++i)
{  count += 1;
   diff = X[i]-mean;
   Mean = Mean + diff/count;
}

To use difference and sum operations appropriate to angles. In C for angles in degrees this is the remainder function, in the math library:

Mean = 0.0
Count = 0;
for ( i=0; i<N; ++i)
{  count += 1;
   diff = remainder(X[i]-Mean, 360.0);
   Mean = remainder( Mean + diff/count, 360.0);
}

Note that remainder() here is not the same as modulus (fmod). From 'man remainder'

The remainder() function computes the remainder of dividing x by y. The return value is x-ny, where n is the value x / y, rounded to the nearest integer. If the absolute value of x-ny is 0.5, n is chosen to be even.

Note the bit about 'rounded to the nearest integer'. So we have, for example,

remainder( 30.0 - 10.0, 360.0) = 20
remainder( 350.0 - 10.0, 360.0) = -20

and so on. If your language doesn't provide such a function, you'll need to implement it yourself, I'm sorry to say I don't know Java so my advice on this would be useless.

dmuir
  • 4,211
  • 2
  • 14
  • 12