Hello all, it's your friendly neighborhood post-n-runner!



Anyway, today's post is a pair of Functions that can be used to convert a Decimal ("computer readable") number into a Fractional ("human readable") number!

First off, I'll point out that yes, decimal numbers are human readable too. However, fractional numbers are most definitely NOT computer readable. And, since there are several industries (and numerous personal projects) that like to see fractional numbers, here's an easy way of providing that.

The code (supplied below) will allow you to specify a "maximum" denominator, essentially telling the computer your smallest value. If the decimal value doesn't fit exactly, then it will be rounded to the closest decimal number that does:

For example, if you try to convert 6.4 into a fractional representation, but specify a maximum denominator of "2", you'll get "6-1/2" since 0.5 is the closest decimal value that can be divided into halves.

A handful of quick examples, and then onto the code!
GetFraction(0.5, 2, " ") = "1/2"
GetFraction(1.5, 2, " ") = "1 1/2"
GetFraction(1.5, 2) = "1-1/2"
GetFraction(1.5, 4) = "1-1/2"
GetFraction(19.375, 16) = "19-3/8"
GetFraction(19.38, 16) = "19-3/8"

Code:
Public Function GetFraction(Number As Double, Optional Denominator As Long = 32, Optional Spacer As String = "-") As Variant
  ' This function returns a fractional representation of a decimal number.

  ' Number = The decimal representation of the number you want to convert.
  '   Required.
  ' Denominator = The max value of the denominator that will be accepted after
  '   conversion. Will round the number as necessary to find the nearest
  '   acceptable value. It ignored, will default to 64ths.
  ' Spacer = The spacing character to be used between the integral and
  '   fractional values of the converted number. Typically a space " " or dash
  '   "-". If ignored, will default to a dash.

  Dim nbrGCD As Long
  Dim nbrNumerator As Long

  GetFraction = -1 ' Initial value!

  If Int(Number) = Number Then
    GetFraction = CStr(Number)
  Else
    ' Round the number to the closest possible value (within the limitations of
    ' our specified Denominator)
    nbrNumerator = CLng((Number - Int(Number)) * Denominator)

    ' Find the GCD of our (rounded) Numerator and Denominator numbers
    nbrGCD = GetGCD(nbrNumerator, Denominator)

    ' Just in case, specify 1 as the lowest possible GCD
    If nbrGCD <= 0 Then
      nbrGCD = 1
    End If

    ' Use the GCD to reduce our fraction to the "lowest" possible value
    nbrNumerator = nbrNumerator / nbrGCD
    Denominator = Denominator / nbrGCD

    ' Return the resulting fractional number (as a String)
    If Int(Number) = 0 Then
      GetFraction = CStr(CLng(nbrNumerator)) & "/" & Denominator
    Else
      GetFraction = CStr(Int(Number)) & Spacer & CStr(CLng(nbrNumerator)) & "/" & Denominator
    End If
  End If
End Function

Public Function GetGCD(Number1 As Long, Number2 As Long) As Long
  Dim nbrN1 As Long
  Dim nbrN2 As Long
  Dim nbrTmp As Long

  nbrN1 = Number1
  nbrN2 = Number2

  Do While nbrN1
    If nbrN1 < nbrN2 Then
      nbrTmp = nbrN1
      nbrN1 = nbrN2
      nbrN2 = nbrTmp
    End If

    nbrN1 = nbrN1 Mod nbrN2
  Loop

  GetGCD = nbrN2
End Function