2011-12-30 11 views
8

Ho un database creato e utilizzato da uno studio di architettura. Tutte le misure sono memorizzate in un formato come questo: 15-3/4 " e 12 '6-3/4".Come convertire una misura visualizzata in un formato architettonico in un punto mobile?

C'è un modo per convertire questi tipi di misure in virgola mobile in Python? O c'è una libreria là fuori che fornisce questa funzionalità?

Allo stesso modo, come si converte da un punto variabile al formato precedente?

+1

Naturalmente c'è un modo. Ma quelli sono valori con unità, quindi la conversione diretta in virgola mobile richiederà anche la definizione dell'unità implicita che sarà. potresti anche perdere la precisione. – Keith

+1

Inoltre, Django è solo un framework web, quindi non ha nulla a che fare con questo. Ora puoi creare un oggetto, che quando è stato scritto in stringa produce quel formato. Quindi puoi semplicemente usare qualsiasi modello. – Keith

+0

Grazie Keith ... Ho rimosso la porzione Django. – Clayton

risposta

3

A seconda di come regolari i modelli sono, è possibile utilizzare str.partition di fare il parsing:

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

Questo non funzionerà se il numero è in pollici frazionari come '3/4" '. Può essere vorresti semplicemente attaccare con rpartition – Abhijit

+0

@Abhijit Modificato per usare rpartition per la separazione int/frac Grazie –

+0

Questo funziona benissimo ... Grazie Raymond! – Clayton

0

architettonica a virgola mobile:

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) 

E 'davvero atroce, ma non ho lavorato con Python in un po'; Non dubito che ci sia un modo molto più pulito per farlo, ma gestisce bene la mancanza di piedi. Lo fa si aspetta sempre i pollici, tuttavia, per cui le misurazioni come 12' devono essere analizzate correttamente da 12' 0".

1

Si consideri il seguente codice commentato automaticamente. Ho cercato di tenere in modo semplice

>>> 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)  

Acid Test

>>> 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 

Conversione da Float a Architettura sarebbe facile come non c'è bisogno di prendere il dolore per l'analisi

>>> 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) 

Acid Test

>>> 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" 
>>> 

Nota *** È importante mantenere la rappresentazione del galleggiante nel minimo denominatore (pollici) o nel massimo rappresentante (piedi). Ho optato per il più alto in questo caso i piedi. Se wan't per abbassarlo è possibile moltiplicarlo per 12.


Update per soddisfare arrotondamento Richiesta (non so se questo è elegante ma non il lavoro)

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

Per il commento di Keith, vorrei aggiungere unità a questo e trasformare il float in una struct o in una classe con un float e un'unità. –

+0

@JesseSmith, devi solo convertirlo in una stringa e aggiungere l'unità. Per ex 'str (Arch2Float ('12 \ '6-3/4"')) + 'ft'' – Abhijit

+0

@Abhijit, anche questa soluzione funziona: ho combinato @RaymondHettinger con la funzione 'Float2Arch'. suggerisci di arrotondare il valore restituito in modo che un input come questo ** 18.33 ** restituisca ** 18 '4 "**? – Clayton

Problemi correlati