If you look up Angle in the Wikipedia, it claims that there are four (4) methods of measuring angles: Degrees, Radians, Turns, and Gons. But they are really five (5) and that is BAM or Binary Angular Measurement.

If we get rid of Turns, and Gons. That leaves three (3): Degrees, Radians, BAM. Only Radians and Degrees units of measurement do well with Floating Point math.  But when we use BAMs its BAM32 or BAM16 and they are Fixed Point Math. So I will show you Degrees to Radian back to Degrees and will show you the math behind a BAM (Not Fixed Point).


SSR Engineering, Inc. "BAMs are used to represent an angular measure; there are 65,535 BAMs per 360°.  An angle provided in BAMs can be converted to degrees by the following relationship:"
Angle (Degrees) = (360 / 65,535) * Angle (BAMs)

, You can re-write this as follows to make this universal:

where Angle, Bams are variables

where n represents the power of 2

Angle = (360 / 2**(n-1)) * Bams


Therefore you can rewrite this into a function:


typedef int degrees;

degrees Bams2degrees(  double Bans, int n){

    return (360/ pow(2,(n-1)) * Bams); }


This is written in  ANSI C. I have typedef both Degrees and Radians, to make the library more readable.



typedef double Degrees;

typedef double Radians;

Radians <> Degrees
Nautical Miles
DMS <> Degrees

// Radians 2 Degrees

Degrees rad2d( Radians rad ) {
  return( rad * 180.0/pi );}

//  Knots 2 Degrees

double kn2d( double knots ) {

return( knots/60 );}

//  Nautical Miles 2 Degrees

Degrees nm2d( double d ){

return( d * pi/180.0 * 60.0 );}

// dms2d should take any struct of type dms_s  and convert to degrees

double dms2d( struct dms_s DMS) {
double d1, m; Degrees d;

Degrees d;
m = DMS.S/60.0;
d1 = (m + DMS.M)/60.0;
d = DMS.D + d1;

// Degrees 2 Radians

Radians d2rad( Degrees d ) {

  return( d * pi/180.0 );}

//  Knots 2 MPH

double kn2mph( double knots ){

return( d2rad( kn2d( knots )));}

//  Degrees 2 Nautical Miles

double d2nm( Degrees d ) {
return( d * 180.0 * 60.0/pi );}

Note that the C Math Library does not have pi defined:

pi = atan2(1,1) *4;


struct dms_s {

  Degrees deg;

  char hemisphere;  // This is a hold over from Perl and not used





struct location_s {

  char ID[5]; // IDs are 4 letters long + trailing \n"

  struct dms_s NS;

  struct dms_s EW;

  double alt; // Station altitude. in feet



struct DMS_s {

double D;  // Degrees

double M; // Minutes

double S; // Seconds

} DMS;

//  Nautical Miles 2 Standard Mile 

double nm2sm( double nm ) {

return( nm * 1.151 );}

// d2dms should take a decimal angle and convert it to any struct of type dms_s
void d2dms( Degrees d ){
int s;
//  the +0.5 is to get rid of the rounding errors.
//  there are 3600 seconds in one degree
s = (int)(d*36000000+0.5);
DMS.S = s%600000/10000.0;
s = s/600000.0;
DMS.M = s%60;
s = s/60;
//  the %360 is to make sure that we don't report 360 degrees.
DMS.D = s%360;

// Radians 2 Nautical Miles

Radians2nm( Radians rad ){

return( rad * 3437.7387 );}


I have included the following information for a .h or header file.


Description of Functions
Function header file information
Degrees to:
Degrees 2 DMSvoid d2dms( Degrees d );
Degrees 2 Nautical Milesdouble d2nm( Degrees d );
Degrees 2 RadiansRadians d2rad( Degrees d );
DMS 2 Dregees double dms2d( struct dms_s DMS);
Knots to:
Knots 2 Degreesdouble kn2d( double knots );
Knots 2 MPHdouble kn2mph( double knots );
Nautical Miles to:
Nautical Miles 2 DegreesDegrees nm2d( double d );
Nautical Miles 2 Standard Miledouble nm2sm( double nm );
Radians to:
Radians 2 DegreesDegrees rad2d( Radians rad )
Radians 2 Nautical MileRadians2nm( Radians rad );


I have included the following description of a BAM. This is what  a BAM16 is.  You can create BAM32 with which you can describe any location on Earth with the size of a postage stamp.

Real Time Systems Design And Analysis

Chapter 7.5.3. - Binary Angular Measure

By Phillip A. LaPlante

Another type of scaled number is based on the property that adding 180o to any
angle is analogous to taking its two’s complement. This technique, called binary angular measurement (BAM) works as follows.
Consider the LSB of an n-bit word to be 2n−1 · 180 degrees with the most significant bit (MSB) = 180 degrees.
The range of any angle θ represented this way is 0 ≤ θ ≤ 360 − 180 · 2(n−1)

degrees. A 16-bit BAM word is shown in Figure 7.6. For more accuracy, BAM can be extended to two more words.

Each n-bit word has a maximum value of:  2n - 2-(n−1) · 180o  = 360o - LSB

with granularity: 2-(n−1) · 180o  = LSB


Consider the 16-bit BAM word:  0000 0000 10100 110

Its binary angular measurement is 166 · 180o · 2−15 = 0.9118o.


180904522.5..............................180 · 2-14180 · 2-15
Figure 7.6 16 bit Binary Angular Mesurement word [Lapante]


BAM can be added and subtracted together and multiplied and divided by constants as if they were unsigned integers, and converted at the last stage to produce floating-point results.

It is easy to show that the overflow condition for BAM numbers presents no problem as the angle simply wraps around to 0.

BAM is frequently used in navigation software, robotic control, and in conjunction with digitizing imaging devices.