Download text file
The functions below do about the same thing. One just takes longer and is
just a bit more accurate.

I converted the long function from VB code by Jay Tanner who
based his code on the mathematical method of H. Andoyer.

The short function is all over the web and I'm not sure which one I used.

Oh, ya, if you've got questions, don't ask me! I'm not the mathmatician.

#COMPILE EXE
#DEBUG ERROR ON
#DIM ALL

%LongCompute = 1

MACRO Pi = 3.14159265358979##

#IF %LongCompute
FUNCTION Geo_Dist_Between (BYVAL Lat1 AS EXTENDED, _
                           BYVAL Lng1 AS EXTENDED, _
                           BYVAL Lat2 AS EXTENDED, _
                           BYVAL Lng2 AS EXTENDED, _
                       OPT BYVAL UoM   AS LONG      ) AS EXTENDED

  DIM C   AS LOCAL EXTENDED
  DIM CF  AS LOCAL EXTENDED
  DIM CL  AS LOCAL EXTENDED
  DIM CG  AS LOCAL EXTENDED
  DIM D   AS LOCAL EXTENDED
  DIM F   AS LOCAL EXTENDED
  DIM G   AS LOCAL EXTENDED
  DIM H1  AS LOCAL EXTENDED
  DIM H2  AS LOCAL EXTENDED
  DIM L   AS LOCAL EXTENDED
  DIM O   AS LOCAL EXTENDED
  DIM R   AS LOCAL EXTENDED
  DIM S   AS LOCAL EXTENDED
  DIM SF  AS LOCAL EXTENDED
  DIM SG  AS LOCAL EXTENDED
  DIM SL  AS LOCAL EXTENDED
  DIM W1  AS LOCAL EXTENDED
  DIM W2  AS LOCAL EXTENDED
  DIM T1  AS LOCAL EXTENDED
  DIM T2  AS LOCAL EXTENDED

  F = (Lat1 + Lat2) / 2                 ' Compute auxiliary angles
  G = (Lat1 - Lat2) / 2
  L = (Lng1 - Lng2) / 2

  T1 = Pi / 180##                       ' Compute sines and cosines of auxiliary angles
  SG  = SIN(G * T1) : CG = COS(G * T1)
  SF  = SIN(F * T1) : CF = COS(F * T1)
  SL  = SIN(L * T1) : CL = COS(L * T1)

  W1 = SG * CL : W1 = W1 * W1
  W2 = CF * SL : W2 = W2 * W2
  S  = W1 + W2

  W1 = CG * CL: W1 = W1 * W1
  W2 = SF * SL: W2 = W2 * W2
  C  = W1 + W2

  O = ATN(SQR(S / C))
  R = SQR(S * C) / O
  D = 2 * O

  SELECT CASE UoM
    CASE 1    : D = D * 3963.10##   ' Miles
    CASE 2    : D = D * 3443.90##   ' Nautical Miles
    CASE ELSE : D = D * 6378.14##   ' Kilometers
  END SELECT

  H1 = (3 * R - 1) / (2 * C)
  H2 = (3 * R + 1) / (2 * S)


  T1 = 0.0033528131778969144                ' Compute the angle between the points on a
  W1 = SF * CG : W1 = W1 * W1 * H1 * T1 + 1 ' synthetic sphere connecting the two points.

  W2 = CF * SG : W2 = W2 * W2 * H2 * T1

  FUNCTION = D * (W1 - W2)                  ' Return the distance between the given locations

END FUNCTION

#ELSE

FUNCTION Geo_Dist_Between (BYVAL Lat1 AS EXTENDED, _
                           BYVAL Lng1 AS EXTENDED, _
                           BYVAL Lat2 AS EXTENDED, _
                           BYVAL Lng2 AS EXTENDED, _
                       OPT BYVAL UoM   AS LONG      ) AS EXTENDED

  DIM Tmp AS LOCAL EXTENDED

  Lng1 = Lng1 / 57.29577951308232##
  Lat1 = Lat1 / 57.29577951308232##
  Lng2 = Lng2 / 57.29577951308232##
  Lat2 = Lat2 / 57.29577951308232##

  Tmp  = (SIN(Lat1) * SIN(Lat2))
  Tmp  = Tmp + (COS(Lat1) * COS(Lat2) * COS(Lng1 - Lng2))
  Tmp  = (Pi / 2) - ATN(Tmp / SQR(1-Tmp*Tmp))  'ArcCos

  SELECT CASE UoM
    CASE 1    : Tmp = Tmp * 3963.10##   ' Miles
    CASE 2    : Tmp = Tmp * 3443.90##   ' Nautical Miles
    CASE ELSE : Tmp = Tmp * 6378.14##   ' Kilometers
  END SELECT

  FUNCTION = Tmp

END FUNCTION
#ENDIF
'
'-----------------------------------------
'
FUNCTION PBMAIN ()

  DIM Cty1  AS LOCAL STRING
  DIM D     AS LOCAL LONG
  DIM Dist  AS LOCAL EXTENDED
  DIM Lat1  AS LOCAL EXTENDED
  DIM Lat2  AS LOCAL EXTENDED
  DIM Lng1  AS LOCAL EXTENDED
  DIM Lng2  AS LOCAL EXTENDED
  DIM Miles AS LOCAL STRING
  DIM Txt   AS LOCAL STRING
  DIM UoM   AS LOCAL LONG

  UoM  = 1   ' 0 = Km, 1 = Miles, 2 = Nautical Miles

  SELECT CASE UoM
    CASE 1    : Miles = " Miles "
    CASE 2    : Miles = " Naut. Miles "
    CASE ELSE : Miles = " Kilometers "
  END SELECT

  Lat1 = VAL(READ$(1))
  Lng1 = VAL(READ$(2))
  Cty1 = READ$(3)

  FOR D = 4 TO DATACOUNT STEP 3
    Lat2 = VAL(READ$(D  ))
    Lng2 = VAL(READ$(D+1))
    Dist = Geo_Dist_Between(Lat1,Lng1,Lat2,Lng2,UoM)
    Txt  = Txt & FORMAT$(ROUND(Dist,2),"00#.#0") & Miles & Cty1 & " -> " & READ$(D+2) & $CRLF
  NEXT

  Txt = RTRIM$(Txt)
#IF %DEF(%PB_CC32)
  FOR UoM = 1 TO PARSECOUNT(Txt,$CRLF)
    PRINT PARSE$(Txt,$CRLF,UoM)
  NEXT
  INPUT FLUSH
  WAITKEY$
#ELSE
  MSGBOX Txt
#ENDIF

  '    Latitude   Longitude    City                  Zip   Rand McNally distance
  DATA 39.929597, -91.374150,  "Quincy, IL"      : ' 62301
  DATA 38.631551, -90.193000,  "St. Louis, MO"   : ' 63101 Should be 138 miles
  DATA 39.800950, -89.649990,  "Springfield, IL" : ' 62701 Should be 118 miles
  DATA 41.886456, -87.623250,  "Chicago, IL"     : ' 60601 Should be 316 miles

END FUNCTION