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

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,046
  • 2
  • 15
  • 11