similarUnits.frink

View or download similarUnits.frink in plain text format


/** This file contains routines that find similar units to a value that you
    may have.
*/

similarUnits[x, maxNum=20] :=
{
   result = ""
   values = unitsWithValues[x]
   numFound = 0
   ratios = new array
   
   for [name, value] = values
   {
      if value == x
      {
         result = result + "1 $name\t(exact match)\n"
         numFound = numFound + 1
      } else
      {
         if realSignum[value] == 0
            next
         ratio = x / value
         ratios.push[ [name, value, ratio] ]
      }
   }

   if numFound >= maxNum
      return result

   // Sorting function
   // This sorts integer and rational first, with smaller ratios being first
   sortFunc = {|a,b|
                    r1 = a@2
                    r2 = b@2

                    if isIntegerOrRational[r1]
                       if isIntegerOrRational[r2]
                          // Both integer or rational
                          return numerator[r1]*denominator[r1] <=> numerator[r2]*denominator[r2]
                       else  // r1 is rational and thus closer
                          return -1
                    else
                       if isIntegerOrRational[r2] // Only r2 rational
                          return 1
                       else     // Neither rational, return closest to 1
                          return abs[log[abs[r1]]] <=> abs[log[abs[r2]]]
               }

   sort[ratios, sortFunc]

   for i = 0 to min[maxNum - numFound, length[ratios]-1]         
   {
      [name, value, ratio] = ratios@i
      result = result + "$ratio $name\n"
   }

   return result
}

/** This returns an array of unit names and their values as [name, value] pairs. */
unitsWithValues[x] :=
{
   result = new array
   for u = units[x]
      result.push[ [u, unit[u]] ]

   return result
}

isIntegerOrRational[n] := isInteger[n] or isRational[n]


View or download similarUnits.frink in plain text format


This is a program written in the programming language Frink.
For more information, view the Frink Documentation or see More Sample Frink Programs.

Alan Eliasen was born 17590 days, 6 hours, 56 minutes ago.