2011-12-30 6 views
8

Tengo una base de datos creada y utilizada por una empresa de arquitectura. Todas las medidas se almacenan en un formato como este: 15-3/4 " y 12 '6-3/4".¿Cómo convertir una medida mostrada en un formato arquitectónico en un punto flotante?

¿Hay alguna forma de convertir estos tipos de mediciones en coma flotante en Python? ¿O hay una biblioteca que ofrece esta funcionalidad?

Del mismo modo, ¿cómo convertirías de un punto flotante al formato anterior?

+1

Por supuesto que hay una manera. Pero esos son valores con unidades, entonces la conversión directa a punto flotante también requerirá definir la unidad implícita que será. también podrías perder precisión. – Keith

+1

Además, Django es solo un framework web, por lo que realmente no tiene nada que ver con esto. Ahora podría crear un objeto, que cuando se convierte en stringified produce ese formato. Entonces puedes usar cualquier plantilla. – Keith

+0

Gracias Keith ... Eliminé la parte de Django. – Clayton

Respuesta

3

Dependiendo de cómo regulares son los patrones, puede utilizar str.partition para hacer el análisis sintáctico:

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

Esto no funcionará si el número es en pulgadas fraccionales como '3/4 ''. Puede ser solo querría seguir con rpartition – Abhijit

+0

@Abhijit Editado para usar rpartition para la separación int/frac. Gracias. –

+0

Esto funciona genial ... Gracias Raymond! – Clayton

0

arquitectónico de punto flotante:

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) 

Es realmente atroz, pero no he trabajado con Python desde hace tiempo; No dudo que haya una manera mucho más limpia de hacerlo, pero maneja bien la falta de pies. Es does siempre esperan pulgadas, por lo que las mediciones como 12' tendrían que ser 12' 0" para analizarse correctamente.

1

Considere el siguiente código de autocomentarios. Traté de mantener de manera sencilla

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

la conversión de Flotante a la arquitectura sería fácil, ya que no tiene que tomar el dolor a analizar

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

Ácido Prueba

>>> 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 *** Es importante mantener la representación de flotación en el denominador más bajo (pulgada) o el denominador más alto representado (pies). Opté por el más alto en este caso pies. Si quieres probar a bajarlo puedes multiplica por 12.


actualización para atender Redondeo Solicitud (No estoy seguro si esto es elegante, pero hace el trabajo)

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

Por el comentario de @ Keith, agregaría una unidad a esto y convertiría el flotador en una estructura o clase con un flotador y una unidad. –

+0

@JesseSmith, solo tiene que convertirlo en una cadena y agregar la unidad. Para ex 'str (Arch2Float ('12 \ '6-3/4"')) + 'ft'' – Abhijit

+0

@Abhijit, estas soluciones también funcionan. He combinado @RaymondHettinger con su función 'Float2Arch'. ¿Cómo lo haría? sugerir redondear el valor devuelto para que una entrada como esta ** 18.33 ** devuelva ** 18 '4 "**? – Clayton

Cuestiones relacionadas