Feet And Inches

July 1, 2011

Drawing programs measure distances in ten-thousandths of an inch, like 73.0185, but carpenters work in feet, inches, and thirty-seconds of an inch, like 6 feet 1 and 1/32 inches.

Your task is to write a program that takes a measurement in decimal notation and returns the measurement in carpenter’s notation; readers unfamiliar with imperial measurements will want to know that there are twelve inches in a foot. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

About these ads

Pages: 1 2

15 Responses to “Feet And Inches”

  1. My Haskell solution (see http://bonsaicode.wordpress.com/2011/07/01/programming-praxis-feet-and-inches/ for a version with comments):

    import Data.Ratio
    import Text.Printf
    
    toCarpenter :: RealFrac a => a -> (Int, Int, Ratio Int)
    toCarpenter l = (feet, div r 32, mod r 32 % 32) where
        (feet, r) = divMod (round $ l * 32) (32 * 12)
    
    feetAndInches :: RealFrac a => a -> String
    feetAndInches l = case toCarpenter l of
        (0,0,0) -> "0 feet 0 inches"
        (f,i,t) -> showUnit "foot" "feet" (f % 1) ++
                   (if f > 0 && (i%1 + t) > 0 then " " else "") ++
                   showUnit "inch" "inches" (i % 1 + t)
        where
        showUnit _ _ 0 = ""
        showUnit s m n = printf "%s %s" (showVal n) $ if n <= 1 then s else m
        showVal v | d == 1    = show n
                  | v < 1     = printf "%d/%d" n d
                  | otherwise = printf "%d and %d/%d" (div n d) (mod n d) d
                  where (n,d) = (numerator v, denominator v)
    
  2. [...] today’s Programming Praxis exercise, our goal is to convert a decimal length value to the fractions used by [...]

  3. T said

    Here’s a Python solution:

    from math import floor
    from fractions import Fraction
    
    def convert(n):    
        feet, r = int(floor(n) / 12), n % 12
        inches  = int(floor(r))
        numer   = int(round(32 * (r - inches)))
        
        return feet, inches, Fraction(numer, 32)
    
    # the rest is just pretty-printing
    
    def show_inches(inches, fractions):
    
        def pluralize_inches(i):
            if i == 1:
                return str(i) + " inch"
            else:
                return str(i) + " inches"
        
        if inches and fractions:
            return str(inches) + ' and ' + str(fractions) + ' inches'
        elif inches or fractions: 
            return pluralize_inches(inches or fractions)
        else: return ''
    
    def feet_and_inches(n):
    
        def pluralize_feet(ft):
            if not ft:
                return ''
            elif ft == 1:
                return str(ft) + ' foot'
            else:
                return str(ft) + ' feet'
        
        if not n:
            return "0 feet 0 inches"
        else:
            feet, inches, fractions = convert(n)
            ft = pluralize_feet(feet)
            i  = show_inches(inches, fractions)
            return ft + (ft and i and ' ') + i
    

    Also here: http://paste.pocoo.org/show/426731/ and here: http://pastebin.com/McZHhzK0

  4. arturasl said

    My solution in Python:

    #!/usr/bin/python3
    
    import sys
    import fractions
    
    if __name__ == '__main__':
        if len(sys.argv) < 2:
            sys.stderr.write('Usage: {0} inches'.format(sys.argv[0]))
            sys.exit(2)
    
        inches = round(float(sys.argv[1]) * 32) / 32
        feets = int(inches // 12)
        inches -= feets * 12
        full = int(inches)
        inches -= full
        numerator = int(inches / (1 / 32))
    
        if (feets, full, numerator) == (0, 0, 0):
            print('0 feet 0 inches')
        else:
            if feets != 0:
                print(feets, 'foot' if feets == 1 else 'feet', end = ' ')
    
            if full != 0:
                print(full, end = ' ')
    
            if numerator != 0 and full != 0:
                print('and', end = ' ')
    
            if numerator != 0:
                print(fractions.Fraction(numerator, 32), end = ' ')
    
            if numerator != 0 or full != 0:
                    print('inches' if full > 1 or (full == 1 and numerator != 0) else 'inch', end = '')
    
            print()
    
  5. Rainer said

    My try in REXX:

    d_inch = 73.0185
    say 'Drawing distance='d_inch '=' convert(d_inch)
    exit
    
    convert:
        parse arg inp	
        parse value inp with vor'.'nach
        aus = ''
        ft = vor % 12
        is = vor // 12
        cz = format(32 / (10000 / nach),2,0)
        if ft > 0 then aus = ft 'feet'
        if is > 0 then aus = strip(aus) is
        if cz > 0 then 
            if strip(aus) > '' then aus = strip(aus) 'and'
    	aus = aus cz'/32'
        return strip(aus)
    
  6. Lautaro Pecile said
    from math import trunc
    from math import modf
    
    
    def carpenter_inches(inches):
        seconds, inches = modf(inches)
        feet, inches = divmod(trunc(inches), 12)
        seconds = trunc(seconds * 32)
        return feet, inches, seconds
    
    
    def string_measure(measure, singular, plural):    
        if measure:
            if measure > 1:
                return "%d %s " % (measure, plural)
            else:
                return "1 %s " % (singular)
        return ''
        
        
    string_feet = lambda n: string_measure(n, 'foot', 'feet')
    string_inches = lambda n: string_measure(n, 'inch', 'inches')
    string_seconds = lambda n: string_measure(n, 'second', 'seconds')
    
    
    string_funcs = [string_feet, string_inches, string_seconds]
    
    
    def show_measure (measure):
        print ''.join([f(n) for f, n in 
                        zip(string_funcs, carpenter_inches(measure))])
    
    
  7. Mike said

    I just used ‘ and ” to indicate feet and inches. Until seeing other’s solutions it hadn’t occured to me to spell them out.

    from math import ceil
    from fractions import Fraction
    
    def convert(m, ppi=32, roundup=False):
        units = int(ceil(m*ppi) if roundup else round(m*ppi))
    
        feet, inch = divmod(units//ppi, 12)
        frac = Fraction(units%ppi, ppi)
    
        return ''.join([
                    "{0}'" if feet or not units else '',
                    " {1}" if inch or not units else '',
                    " {2}" if frac else '',
                    '"' if inch or frac or not units else ''
                    ]).lstrip().format(feet, inch, frac)
    
    
  8. Mike said

    Here’s my version modified to print out “feet” and “inches”.

    from math import ceil
    from fractions import Fraction
    
    def convert(m, ppi=32, roundup=False):
        units = int(ceil(m*ppi) if roundup else round(m*ppi))
    
        if not units: return "0 feet 0 inches"
       
        feet, inches = divmod(units, 12*ppi)
        whole, parts = divmod(inches, ppi)
    
        fmt = ''.join([
            '{0} feet' if feet > 1 else '{0} foot' if feet else '' ,
            ' {1}' if whole else '',
            ' and' if whole and parts else '',
            ' {2}' if parts else '',
            ' inches' if inches > ppi else ' inch' if inches else ''
            ]).lstrip()
    
        return fmt.format(feet, whole, Fraction(parts, ppi))
    
  9. WillJ said

    Here’s one in C++

    #include <iostream>
    
    using namespace std;
    
    void toCarpenter(double dec_inches)
    {
        if( !dec_inches )
        {
            cout << "0 feet and 0 inches" << endl;
            return;
        }
        int inches = dec_inches;
        dec_inches -= inches;
        int feet = inches / 12;
        inches = inches % 12;
        int denominator = 32;
        int numerator = dec_inches * denominator;
        while( numerator % 2 == 0 )
        {
            numerator /= 2;
            denominator /= 2;
        }
        if( feet )
        {
            cout << feet;
            feet > 1 ? cout << " feet " : cout << " foot ";
        }
        if( inches )cout << inches;
        if( inches && numerator ) cout << " and ";
        if( numerator ) cout << numerator << "/" << denominator;
        inches > 1 ? cout << " inches" : cout << " inch";
    }
    
    
    int main()
    {
        double inches = 26.375;
        toCarpenter( inches );
    }
    
  10. jeff lindholm said

    namespace Carpenter
    {
    class Program
    {
    static void Caprenter(double measureInches, out int feet, out int inches, out int thirtyseconds)
    {
    feet = (int)(measureInches / 12);
    inches = (int)(measureInches % 12);
    thirtyseconds = (int)((measureInches – (feet * 12) – inches) * 32.0);
    }
    static void Main()
    {
    double measureInches = 26.375;
    int feet, inches, thirtyseconds;
    Caprenter(measureInches, out feet, out inches, out thirtyseconds);
    System.Console.WriteLine(“Feet {0}, Inches {1}, 1/32 {2}”, feet, inches, thirtyseconds);
    }
    }
    }

  11. markmain said

    This is written in Excel VBA; it is called using: =CarpenterNotation(A1) for the defaults, or by selecting the varous optional parameters.
    It can optionally round to various fractions, or 16th’s are the default; typical values would be 8 for 8ths or 16 for 16ths of an inch.
    It can optionally round up or down, otherwise standard rounding occurs.
    It can optionally display a dash on the left or right side for negative numbers, or parenthesis is the default.
    It can optionally display a tilde to represent when the number is now an approximation due to rounding, or not display any notation, or a double-tilde is the default approximation notation.

    Option Explicit
    Public Enum vbNegativeInd
       [_first] = -1
       vbDashOnLeft = -1 'place dash on the left side for negative numbers
       vbParentheses = 0 'place parenthesis around negative numbers
       vbDashOnRight = 1 'place dash on the right side for negative numbers
       [_last] = 1
    End Enum
    
    Public Enum vbRounding
       [_first] = -1
       vbRoundDown = -1  'round down to the nearest fraction
       vbRound = 0       'standard rounding to the nearest fraction
       vbRoundUp = 1     'round up to the nearest fraction
       [_last] = 1
    End Enum
    
    Public Enum vbApproxInd 'approximations are only used when rounding occurs
       [_first] = 0
       vbNoIndicator = 0 'do not indicate approximations
       vbTilde = 1       'indicate approximations with a tilde on the left of the number
       vbDoubleTilde = 2 'indicate apprximatrions with a double-tilde on the left of the number
       [_last] = 2
    End Enum
    
    Public Function CarpenterNotation(ByVal inches As Double, _
                             Optional ByVal smallestFractionSize As Long = 16, _
                             Optional ByVal negativeInd As vbNegativeInd = 0, _
                             Optional ByVal rounding As vbRounding = 0, _
                             Optional ByVal approxInd As vbApproxInd = 2) As String
       'by Mark Main
       'OUTPUT:                 feet, inches and the fraction with negative sign and approximation indicators optionally displayed
       'inches:                 input is in inches with decimal up to 14 decimal places
       'smallestFractionalSize: 16 for 1/16th inch increment, 8 for 1/8th, etc.
       'negativeInd:            (default is 0) equals -1 to place the negative dash on the left side, 0 for parentheses, and +1 for the dash on the right side
       'rounding:               (default is 0) equals 0 for standard rounding, 1 for round-up and -1 for round-down
       'approxInd:              (default is 2) equals 0 for no approximation indicator, 1 for a tilde ~, and 2 for a double-tilde
       '                             double-tilde is also called: "almost equal to", "approximately equals" or "asymptotic to" symbol
       '                             whenever rounding is required the display is then an approximation; the indicator will show this when it happens
       '
       'Note: blanks are provided to help positive numbers align with negative numbers; use Trim to bypass this feature: =Trim(CarpenterNotation(A1))
       
       Dim feet, GCDnum, numerator, denominator As Long
       Dim originalFraction, fraction As Double
       Dim negative As Boolean
       Dim negind, leftparen, rightparen As String
       On Error GoTo CarpenterNotationErr
       
       If inches < 0 Then 'negative number
          negative = True
          inches = Abs(inches)
       End If
       
       'round the fraction to the nearest fraction based upon smallestFractionalSize
       originalFraction = Round(inches - Int(inches), 14) 'rounding at 14 eliminates some unusual floating decimal errors from the Double data type
       Select Case rounding
          Case vbRoundDown:   fraction = Application.WorksheetFunction.RoundDown(originalFraction * smallestFractionSize, 0) / smallestFractionSize
          Case vbRoundUp:    fraction = Application.WorksheetFunction.RoundUp(originalFraction * smallestFractionSize, 0) / smallestFractionSize
          Case Else: fraction = Round(originalFraction * smallestFractionSize, 0) / smallestFractionSize
       End Select
       
       GCDnum = Application.WorksheetFunction.GCD(fraction * smallestFractionSize, smallestFractionSize) 'used to reduce fractions; e.g. 12/16 to 3/4
       
       feet = Int(inches / 12)
       inches = Int(inches - (feet * 12))
       numerator = fraction * 16 / GCDnum
       denominator = 16 / GCDnum
       CarpenterNotation = inches & "-" & numerator & "/" & denominator & """"
       
       If feet <> 0 Then CarpenterNotation = feet & "' " & CarpenterNotation 'feet is ignored if zero
       
       'add negative indicators for negative numbers and blank spaces otherwise
       If negative Then
          negind = "-"
          leftparen = "("
          rightparen = ")"
       Else
          negind = " "
          leftparen = " "
          rightparen = " "
       End If
       Select Case negativeInd
          Case 1:    CarpenterNotation = CarpenterNotation & negind
          Case 0:    CarpenterNotation = leftparen & CarpenterNotation & rightparen
          Case Else: CarpenterNotation = negind & CarpenterNotation
       End Select
          
       'add the approximation indicator if needed
       If fraction <> originalFraction Then 'this is an approximation
          If approxInd = vbTilde Then
             CarpenterNotation = "~" & CarpenterNotation 'tilde added to indicate value is an approximation
          ElseIf approxInd <> vbNoIndicator Then 'default
             CarpenterNotation = ChrW(8776) & CarpenterNotation 'double-tilde added to indicate value is an approximation
          End If
       Else
          If approxInd <> vbNoIndicator Then CarpenterNotation = "  " & CarpenterNotation 'add two blanks to cover for the tilde's
       End If
       On Error GoTo 0
       Exit Function
    
    CarpenterNotationErr:
       On Error GoTo 0
       CarpenterNotation = "#ERROR"
    End Function
    
  12. markmain said

    I made some changes. First I fixed a bug if zero appears in the denominator. I forgot to test for that, so I fixed it. And I made an option to decide if you want to display zero inches when there is feet; otherwise inches will always display if feet is zero.

    Also, I decided to go with no approximation indication (FALSE value) or TRUE value to display approximation by using a tilde to show that the actual value is LESS than the rounded value displayed and I show the double tilde if the actual value is GREATER than what is displayed. This lets you know if the display is just a hair light or heavy simply by looking at the tilde’s.

    So now TRUE/FALSE is used for the last 2 options:

    Option Explicit
    Public Enum vbNegativeInd
       [_first] = -1
       vbDashOnLeft = -1 'place dash on the left side for negative numbers
       vbParentheses = 0 'place parenthesis around negative numbers
       vbDashOnRight = 1 'place dash on the right side for negative numbers
       [_last] = 1
    End Enum
    
    Public Enum vbRounding
       [_first] = -1
       vbRoundDown = -1  'round down to the nearest fraction
       vbRound = 0       'standard rounding to the nearest fraction
       vbRoundUp = 1     'round up to the nearest fraction
       [_last] = 1
    End Enum
    
    Public Function CarpenterNotation(ByVal inches As Double, _
                             Optional ByVal smallestFractionSize As Long = 16, _
                             Optional ByVal negativeInd As vbNegativeInd = 0, _
                             Optional ByVal rounding As vbRounding = 0, _
                             Optional ByVal dispZeroInches As Boolean = True, _
                             Optional ByVal approxIndication As Boolean = True) As String
       'by Mark Main
       'OUTPUT:                 feet, inches and the fraction with negative sign and approximation indicators optionally displayed
       'inches:                 input is in inches with decimal up to 14 decimal places
       'smallestFractionalSize: 16 for 1/16th inch increment, 8 for 1/8th, etc.
       'negativeInd:            (default is 0) equals -1 to place the negative dash on the left side, 0 for parentheses, and +1 for the dash on the right side
       'rounding:               (default is 0) equals 0 for standard rounding, 1 for round-up and -1 for round-down
       'dispZeroInches:         (default TRUE) equals TRUE when zero inches is displayed with the feet; if FALSE zero inches will not be display unless feet equals zero
       'approxIndication:              (default true) equals FALSE for no approximation indicator, or a
       '                         TRUE shows a tilde or double-tilde when rounding causes the number to be smaller or larger respectively to the original number
       '                         double-tilde is also called: "almost equal to", "approximately equals" or "asymptotic to" symbol
       '                         whenever rounding is required the display is then an approximation; the indicator will show this when it happens
       '
       'Note: blanks are provided to help positive numbers align with negative numbers; use Trim to bypass this feature: =Trim(CarpenterNotation(A1))
       
       Dim feet, GCDnum, numerator, denominator As Long
       Dim originalFraction, fraction As Double
       Dim negative As Boolean
       Dim negind, leftparen, rightparen As String
       On Error GoTo CarpenterNotationErr
       
       If inches < 0 Then 'negative number
          negative = True
          inches = Abs(inches)
       End If
       
       'round the fraction to the nearest fraction based upon smallestFractionalSize
       originalFraction = Round(inches - Int(inches), 14) 'rounding at 14 eliminates some unusual floating decimal errors from the Double data type
       Select Case rounding
          Case vbRoundDown:   fraction = Application.WorksheetFunction.RoundDown(originalFraction * smallestFractionSize, 0) / smallestFractionSize
          Case vbRoundUp:    fraction = Application.WorksheetFunction.RoundUp(originalFraction * smallestFractionSize, 0) / smallestFractionSize
          Case Else: fraction = Round(originalFraction * smallestFractionSize, 0) / smallestFractionSize
       End Select
       
       GCDnum = Application.WorksheetFunction.GCD(fraction * smallestFractionSize, smallestFractionSize) 'used to reduce fractions; e.g. 12/16 to 3/4
       
       feet = Int(inches / 12)
       inches = Int(inches - (feet * 12))
       numerator = fraction * 16 / GCDnum
       denominator = 16 / GCDnum
       If numerator > 0 Then
          CarpenterNotation = inches & "-" & numerator & "/" & denominator & """"
       ElseIf dispZeroInches And feet > 0 Or feet = 0 Then
             CarpenterNotation = inches & """" 'zero inches is only displayed when necessary
       End If
       
       If feet <> 0 Then CarpenterNotation = feet & "' " & CarpenterNotation 'feet is ignored if zero
       
       'add negative indicators for negative numbers and blank spaces otherwise
       If negative Then
          negind = "-"
          leftparen = "("
          rightparen = ")"
       Else
          negind = " "
          leftparen = " "
          rightparen = " "
       End If
       Select Case negativeInd
          Case 1:    CarpenterNotation = CarpenterNotation & negind
          Case 0:    CarpenterNotation = leftparen & CarpenterNotation & rightparen
          Case Else: CarpenterNotation = negind & CarpenterNotation
       End Select
          
       'add the approximation indicator if needed
       If approxIndication = True Then 'a tilde or double-tilde will be used when approximation occurs, otherwise blanks
          If fraction < originalFraction Then
             CarpenterNotation = "~" & CarpenterNotation 'tilde added to indicate value is an approximation; rounded value less than the original
          ElseIf fraction > originalFraction Then
             CarpenterNotation = ChrW(8776) & CarpenterNotation 'double-tilde added to indicate value is an approximation; rounded value is greater than original
          Else
             CarpenterNotation = "  " & CarpenterNotation 'add two blanks to cover for the tilde's; zero rounding was needed
          End If
       End If
       
       On Error GoTo 0
       Exit Function
    
    CarpenterNotationErr:
       On Error GoTo 0
       CarpenterNotation = "#ERROR"
    End Function
    
  13. markmain said

    Sorry, I wrote my notes backwards–I wish that I could edit it. For the tilde indication for my code above here is the rules:

    if actual cell value > rounded display value then a tilde
    if actual cell value < rounded display value then a double-tilde

    saying the same thing in the reverse way:

    if rounded display value actual cell value then a double-tilde

  14. markmain said

    This is my final version if you’d like to have it–it’s public domain.
    I added some error checking and found a bug if the value was just barely under 1 foot, 2 feet, etc, then it would round up but show 0/16″ Ooops, sorry. It’s fixed now.
    I have tested this really well and it works solidly, I hope that you like it, sorry for the different versions, but the final product is nice.

    Option Explicit
    Public Enum vbNegativeInd
       [_first] = -1
       vbDashOnLeft = -1 'place dash on the left side for negative numbers
       vbParentheses = 0 'place parenthesis around negative numbers
       vbDashOnRight = 1 'place dash on the right side for negative numbers
       [_last] = 1
    End Enum
    
    Public Enum vbRounding
       [_first] = -1
       vbRoundDown = -1  'round down to the nearest fraction
       vbRound = 0       'standard rounding to the nearest fraction
       vbRoundUp = 1     'round up to the nearest fraction
       [_last] = 1
    End Enum
    
    Public Function CarpenterNotation(ByVal inches As Double, _
                             Optional ByVal smallestFractionSize As Long = 16, _
                             Optional ByVal negativeInd As vbNegativeInd = 0, _
                             Optional ByVal rounding As vbRounding = 0, _
                             Optional ByVal dispZeroInches As Boolean = True, _
                             Optional ByVal approxIndication As Boolean = True) As String
       'by Mark Main
       'OUTPUT:               feet, inches and the fraction with negative sign and approximation indicators optionally displayed
       'inches:               input is in inches with decimal up to 13 decimal places will work, but output rounding is limited to 10 decimals;
       '                      this accuracy is beyond any physical machine measurements
       'smallestFractionSize: 16 for 1/16th inch increment, 8 for 1/8th, etc.; the limit is 100,000, which is rediculously accurate
       'negativeInd:          (default is 0) equals -1 to place the negative dash on the left side, 0 for parentheses, and +1 for the dash on the right side
       'rounding:             (default is 0) equals 0 for standard rounding, 1 for round-up and -1 for round-down
       'dispZeroInches:       (default TRUE) equals TRUE when zero inches is displayed with the feet; if FALSE zero inches will not be display unless feet equals zero
       'approxIndication:            (default TRUE) equals FALSE for no approximation indicator, or a
       '                       TRUE shows a tilde or double-tilde when rounding causes the number to be smaller or larger respectively to the original number
       '                       double-tilde is also called: "almost equal to", "approximately equals" or "asymptotic to" symbol
       '                       whenever rounding is required the display is then an approximation; the indicator will show this when it happens
       '
       'Note: blanks are provided to help positive numbers align with negative numbers; use Trim to bypass this feature: =Trim(CarpenterNotation(A1))
       '      if you don't like the space between the tilde and the number then use a +1 for the negativeInd parameter
       
       Dim feet, GCDnum, numerator, denominator, numMetric As Long
       Dim originalInches, originalFraction, inchFraction, fraction, mmRound, mmOriginal, mmOriginalRound, mm As Double
       Dim negative As Boolean
       Dim negInd, leftParen, rightParen, Measurement, approxSign As String
       On Error GoTo CarpenterNotationErr
       
       If inches < 0 Then 'negative number
          negative = True
          inches = Abs(inches)
       End If
       
       'round the fraction to the nearest fraction based upon smallestFractionSize
       originalInches = inches
       originalFraction = Round(inches - Int(inches), 14) 'rounding at 14 eliminates some unusual floating decimal errors from the Double data type
       If smallestFractionSize > 100000 Then smallestFractionSize = 100000 'there has to be some limit, this provides .00001" accuracy or  1/65536" (1/16^4")
       Select Case rounding
          Case vbRoundDown
             inchFraction = Application.WorksheetFunction.RoundDown(originalFraction * smallestFractionSize, 0) / smallestFractionSize 'round to nearest fraction
          Case vbRoundUp
             inchFraction = Application.WorksheetFunction.RoundUp(originalFraction * smallestFractionSize, 0) / smallestFractionSize 'round to nearest fraction
          Case Else
             inchFraction = Round(originalFraction * smallestFractionSize, 0) / smallestFractionSize 'round to nearest fraction
       End Select
       inches = Int(inches) + inchFraction
       inchFraction = inches - Int(inches)  'must be redone because inches is now rounded correctly
       GCDnum = Application.WorksheetFunction.GCD(inchFraction * smallestFractionSize, smallestFractionSize) 'used to reduce fractions; e.g. 12/16 to 3/4
       numerator = inchFraction * smallestFractionSize / GCDnum
       denominator = smallestFractionSize / GCDnum
       feet = Int(inches / 12)
       inches = Int(inches Mod 12) 'inches in excess of the feet
       If numerator > 0 Then
          CarpenterNotation = inches & "-" & numerator & "/" & denominator & """"
       ElseIf dispZeroInches And feet > 0 Or feet = 0 Then
             CarpenterNotation = inches & """" 'zero inches is only displayed when necessary
       End If
       
       If feet <> 0 Then CarpenterNotation = feet & "' " & CarpenterNotation 'feet is ignored if zero
       
       'add negative indicators for negative numbers and blank spaces otherwise
       If negative Then
          negInd = "-"
          leftParen = "("
          rightParen = ")"
       Else
          negInd = " "
          leftParen = " "
          rightParen = " "
       End If
       Select Case negativeInd
          Case 1:    CarpenterNotation = CarpenterNotation & negInd
          Case 0:    CarpenterNotation = leftParen & CarpenterNotation & rightParen
          Case Else: CarpenterNotation = negInd & CarpenterNotation
       End Select
          
       'add the approximation indicator if needed
       If approxIndication = True Then 'a tilde or double-tilde will be used when approximation occurs, otherwise blanks
          If Not negative And inchFraction < originalFraction Or negative And inchFraction > originalFraction Then
             CarpenterNotation = "~" & CarpenterNotation 'tilde added to indicate value is an approximation; rounded value less than the original
          ElseIf Not negative And inchFraction > originalFraction Or negative And inchFraction < originalFraction Then
             CarpenterNotation = ChrW(8776) & CarpenterNotation 'double-tilde added to indicate value is an approximation; rounded value is greater than original
          Else
             CarpenterNotation = "  " & CarpenterNotation 'add two blanks to cover for the tilde's; zero rounding was needed
          End If
       End If
    
       On Error GoTo 0
       Exit Function
    
    CarpenterNotationErr:
       On Error GoTo 0
       CarpenterNotation = "#ERROR"
    End Function
    
  15. David said

    In FORTH, still rounds down sometimes but mostly correct. Also I just print “inch(es)” as shortcut…

    : even>0?  ( n -- ? )
        dup  1 and 0=  swap 0>  and ;
    
    : rounded ( n -- n )
        10 /mod  swap 5 + 10 / + ;
    
    : .feet  ( n -- )
        ?dup IF
            dup .   1 = IF ." foot " ELSE ." feet " THEN
        THEN ;
    
    : .frac ( n/32 -- )
        32 swap
        BEGIN  dup even>0?  WHILE
            2/  swap 2/  swap
        REPEAT
        0 .r ." /" . ;
    
    : .inches ( frac n -- )
        2dup D0= IF
          2drop
        ELSE
           ?dup 0= IF
               32 1000 */ .frac ." inch"
           ELSE
               . 32 1000 */ ?dup IF ." and " .frac THEN ." inch(es)"
            THEN
        THEN ;
    
    : .carpenter  ( d -- )
        drop
        dup 0= IF
           ." 0 feet 0 inches"
        ELSE
           rounded 1000 /mod 12 /mod .feet .inches
        THEN ;
    

    Execution:

    0.2785 .carpenter 1/4 inch ok
    1.2785 .carpenter 1 and 1/4 inch(es) ok
    11.9999 .carpenter 1 foot  ok
    1.6895 .carpenter 1 and 11/16 inch(es) ok
    72.0000 .carpenter 6 feet  ok
    71.9999 .carpenter 6 feet  ok
    73.0135 .carpenter 6 feet 1 inch(es) ok
    73.8218 .carpenter 6 feet 1 and 13/16 inch(es) ok
    73.0315 .carpenter 6 feet 1 and 1/32 inch(es) ok
    

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 577 other followers

%d bloggers like this: