2011-12-30 5 views
8

У меня есть база данных, которая была создана и используется архитектурной фирмой. Все измерения хранятся в таком формате: 15-3/4 " и 12 '6-3/4".Как преобразовать измерение, отображаемое в архитектурном формате, в плавающую точку?

Есть ли способ преобразовать эти типы измерений в плавающую точку в Python? Или есть библиотека, которая предоставляет эту функциональность?

Аналогично, как бы вы конвертировали из плавающей точки в вышеуказанный формат?

+1

конечно, есть способ. Но это значения с единицами, поэтому преобразование непосредственно в плавающую точку также потребует определения подразумеваемой единицы, которой она будет. вы также можете потерять точность. – Keith

+1

Кроме того, Django - это всего лишь веб-фреймворк, поэтому он действительно не имеет ничего общего с этим. Теперь вы можете создать объект, который, когда stringified производит этот формат. Затем вы можете использовать любой шаблон. – Keith

+0

Спасибо Keith ... Я удалил часть Django. – Clayton

ответ

3

В зависимости от того, как регулярные узоры, вы можете использовать str.partition сделать синтаксический анализ:

def architectural_to_float(text): 
    ''' Convert architectural measurements to inches. 

     >>> for text in """15-3/4",12' 6-3/4",3/4",3/4',15',15",15.5'""".split(','): 
     ...  print text.ljust(10), '-->', architectural_to_float(text) 
     ... 
     15-3/4" --> 15.75 
     12' 6-3/4" --> 150.75 
     3/4"  --> 0.75 
     3/4'  --> 9.0 
     15'  --> 180.0 
     15"  --> 15.0 
     15.5'  --> 186.0 

    ''' 
    # See http://stackoverflow.com/questions/8675714 
    text = text.replace('"', '').replace(' ', '') 
    feet, sep, inches = text.rpartition("'") 
    floatfeet, sep, fracfeet = feet.rpartition('-') 
    feetnum, sep, feetdenom = fracfeet.partition('/') 
    feet = float(floatfeet or 0) + float(feetnum or 0)/float(feetdenom or 1) 
    floatinches, sep, fracinches = inches.rpartition('-') 
    inchesnum, sep, inchesdenom = fracinches.partition('/') 
    inches = float(floatinches or 0) + float(inchesnum or 0)/float(inchesdenom or 1) 
    return feet * 12.0 + inches 
+0

Это не сработает, если число находится в дробном дюйме, как '3/4" '. Может быть, вы просто захотите придерживаться rpartition – Abhijit

+0

@Abhijit Отредактировано для использования rpartition для разделения int/frac. Спасибо. –

+0

Это отлично работает ... Спасибо Raymond! – Clayton

0

Architectural с плавающей точкой:

import re 

regex = re.compile('(\d+\')*(\d+)-(\d+)\/(\d+)"') 
regex.sub(lambda m: str((int((m.group(1) or '0').split("'")[0]) * 12) 
    + int(m.group(2))) 
    + ('%.2f' % (int(m.group(3))/float(m.group(4))))[1:], measurement) 

Это действительно отвратительный, но я не работал с Python в то время; Я не сомневаюсь, что есть намного более чистый способ сделать это, но он отлично справляется с отсутствием ног. Это делает всегда ожидать дюймов, хотя, поэтому измерения, такие как 12', должны были бы быть 12' 0" для правильной обработки.

1

Рассмотрите следующий код с комментариями. Я пытался сохранить в простом

>>> from fractions import Fraction 
>>> def Arch2Float(num): 
    #First Partition from Right so that the Feet and Unit always 
    #Remains aligned even if one of them is absent 
    ft,x,inch=num.rpartition("\'") 
    #Convert the inch to a real and frac part after stripping the 
    #inch (") identifier. Note it is assumed that the real and frac 
    #parts are delimited by '-' 
    real,x,frac=inch.strip("\"").rpartition("-") 
    #Now Convert every thing in terms of feet which can then be converted 
    #to float. Note to trap Error's like missing or invalid items, its better 
    #to convert each items seperately 
    result=0 
    try: 
     result = int(ft.strip("\'")) 
    except ValueError: 
     None 
    #Convert the real inch part as a fraction of feet 
    try: 
     result += Fraction(int(real),12) 
    except ValueError: 
     None 
    #Now finally convert the Fractional part using the fractions module and convert to feet 
    try: 
     result+=Fraction(frac)/12 
    except ValueError: 
     None 
    return float(result)  

лакмусовой бумажкой

>>> print Arch2Float('15-3/4"')  # 15-3/4" (without ft) 
1.3125 
>>> print Arch2Float('12\' 6-3/4"') #12' 6-3/4" 
12.5625 
>>> print Arch2Float('12\'6-3/4"') #12'6-3/4" (without space) 
12.5625 
>>> print Arch2Float('3/4"')  #3/4" (just the inch) 
0.0625 
>>> print Arch2Float('15\'')  #15' (just ft) 
15.0 
>>> print Arch2Float('15')   #15 (without any ascent considered as inch) 
1.25 

Преобразование из Float в архитектуре было бы легко, как вы не должны взять боль, чтобы разборе

>>> def Float2Arch(num): 
    num=Fraction(num) 
    ft,inch=Fraction(num.numerator/num.denominator),Fraction(num.numerator%num.denominator)/num.denominator*12 
    real,frac=inch.numerator/inch.denominator,Fraction(inch.numerator%inch.denominator,inch.denominator) 
    return '{0}\' {1}-{2}"'.format(ft,real,frac) 

кислота Испытание

>>> print Float2Arch(Arch2Float('12\' 6-3/4"')) 
12' 6-3/4" 
>>> print Float2Arch(Arch2Float('15-3/4"')) 
1' 3-3/4" 
>>> print Float2Arch(Arch2Float('12\'6-3/4"')) 
12' 6-3/4" 
>>> print Float2Arch(Arch2Float('3/4"')) 
0' 0-3/4" 
>>> print Float2Arch(Arch2Float('15\'')) 
15' 0-0" 
>>> print Float2Arch(Arch2Float('15')) 
1' 3-0" 
>>> 

Примечание *** Важно сохранить представление с плавающей точкой как в самом нижнем знаменателе (дюйме), так и в наивысшем представленном знаменателе (футах). Я выбрал самый высокий в этом случае ноги. Если вы wan't снизить его можно умножить на 12.


Update, чтобы удовлетворить запрос Округление (не уверен, если это элегантный, но делает работу)

def Float2Arch(num): 
    num=Fraction(num) 
    ft,inch=Fraction(num.numerator/num.denominator),Fraction(num.numerator%num.denominator)/num.denominator*12 
    real,frac=inch.numerator/inch.denominator,Fraction(inch.numerator%inch.denominator,inch.denominator) 
    for i in xrange(1,17): 
     if Fraction(frac) < Fraction(1.0/16*i): break 
    frac=Fraction(1.0/16*i) 
    if frac>= 1: 
     real+=1 
     frac=0 
    return '{0}\' {1}-{2}"'.format(ft,real,frac) 
+0

Комментарий Пер @ Кита, я бы добавил блок к этому и превратил float в структуру или класс с поплавком и единицей. –

+0

@JesseSmith, вам просто нужно преобразовать его в строку и добавить блок. Для ex 'str (Arch2Float ('12 \ '6-3/4"')) + 'ft'' – Abhijit

+0

@Abhijit, эти решения также работают. Я объединил @RaymondHettinger с функцией 'Float2Arch'. Как бы вы предложите округлить возвращаемое значение, так что вход вроде этого ** 18.33 ** возвращает ** 18 '4 "**? – Clayton