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.

Pages: 1 2

16 Responses to “Feet And Inches”

```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
```
16. jeff said

here’s a python solution i came up with.. precision can be changed in line 6&7… change the 16 to 4, 8, 32, 64 etc.. (it’s in 16ths right now as that’s typically what carpenters use)

```import math
import fractions

def feet_inches(decimal):

tol = round(decimal * 16)
a = math.modf(tol / 16)

feet = int(a[1] // 12)
inch = int(a[1] % 12)
fract = fractions.Fraction(a[0])
if fract == 0:
fract = ""

fi= str(feet)+" - "+str(inch)+" "+str(fract)
return fi

print feet_inches(88.3493475525)
```

7 – 4 3/8