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 17897 days, 19 hours, 44 minutes ago.