public class Angle
implements java.lang.Cloneable, java.lang.Comparable<Angle>, java.io.Serializable
Angles as objects that know what units they are in, know how to do trigonometry without
needing help with unit conversion, and are therefore much less error-prone in lengthy calculations.
In java.lang.(Strict)Math you have to keep track of whether an angle is in degrees or radians when you use
trigonometrical functions; the present class knows what to do, so you can forget about it! This should reduce
the potential for errors of the degrees/radians kind.
A continual refrain in Jean Meeus' excellent series of books on astronomical computation is the risk of errors
due to the fact that angles are usually given in degrees but trigonometry requires radians. It is vital to keep
track of this in programs and ensure that conversions between units happen correctly. There is nothing to tell
from a numerical value by itself what the units are supposed to be.
A first defence against radian/degree confusion is to include the unit names in the names of variables. Eg,
latitudeDegrees = 45. That helps to keep track of what the units are supposed to be at any point in a
calculation but it does not ensure that they are in fact correct.
So for taking a cosine you could write
x = cos (toRadians (latitudeDegrees))
and the "Degrees" in the variable name helps you to remember to call the function to convert it to radians
first. But it does not guarantee that you will do that. Importantly, the compiler cannot detect such an error
because whether the toRadians () function is called or not, the argument to cos () is a number and that's all
the compiler requires.
In object-oriented languages there is a better remedy: make angles into objects rather than merely numbers. The
class definition for Angle can then contain trigonometrical functions that know what units the angle is in and
therefore can always do the right thing:
Angle latitude = new Angle (45.0, DEGREES);
x = latitude.cos ();
Now the conversion to, and use of, appropriate units is hidden inside the class/object. We don't need to know
whether internally the value is held in degrees or radians (though for performance in intensive geometrical
calculations it probably ought to be radians). Provided that the class has been thoroughly (unit-) tested the
kind of mistake we were discussing simply cannot occur. (In the example DEGREES is meant to be a constant - in
Java it would be an enum.)
Astronomical quantities such as RA and Dec are angles and so they too should be declared as classes: subclasses
In the object-oriented language Java (and as far as I know in all commonly used programming languages) this
idea has NOT been adopted in the standard library. A Java class called Math has (static) trigonometrical
functions taking angles in radians as their arguments. I contend that a much better basis for astronomical
computing should declare Angle as outlined above. Angle uses Math internally but any further geometrical
programming should only use objects of class Angle. The application programmer should never directly use Math
for trigonometry. Inverse functions should be defined as functions (in Java, static methods) creating new Angle
Angle phi = Angle.atan (x);
A further benefit of using Angle as a class, and therefore as a data type, is that where functions take several
parameters which would otherwise just be a list of numbers, it then becomes clear that particular ones are
angles. That again reduces errors, of the kind where the parameters are written in the wrong order.
public static Angle parseAngle(java.lang.String s)
Allow all possible formatting of the String. Eg,
123.45678 (decimal degrees if part before point is less than 10000)
-123 27 18.3
123 27m18.3 (can be any single non-digit separators between sub-fields)
but not 274.3 which would have to be 20704.3 to be unambiguous.
Leading sign is allowed.