Grad-rechner

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Nichts besodneres aber vllt kanns der Ein oder Andere gebrauchen

Celsius -> Fahrenheit
Fahrenheit -> Celsius
Celsius -> Kelvin
Kelvin -> Celsius

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-

from __future__ import division

def f2c(fahrenheit):
    return (fahrenheit - 32) * 5/9

def c2f(celsius):
    return 9/5 * celsius + 32

def c2k(celsius):
    return celsius + 273.15

def k2c(kelvin):
    return kelvin - 273.15

if __name__ == '__main__':
    print 'f2c: ° Celsius:', f2c(77)
    print 'c2f: ° Fahrenheit:', c2f(-43)
    print 'c2k: ° Kelvin:', c2k(0)
    print 'k2c: ° Celsius', k2c(273.15)
Sind die Funktionsnamen ok, oder zu nichtssagend?
the more they change the more they stay the same
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

Ist ja wirklich ein Grossprojekt.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Ja, hab mir vorgenommen es noch zu erweitern auf so ziemlich alle Einheiten, demnächst und es hier zu posten
the more they change the more they stay the same
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

Das hier ist empfehlenswert. Zwar nicht Python und am Ende Java basierend, aber nicht schlecht.
http://futureboy.us/frinkdocs/
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ich würde ja stets über Kelvin gehen. Wenn man n Größen hat, macht es wenig Sinn n*(n-1)-Konverter zu schreiben, sondern nur jeweils einen fürs hin- und herkonvertieren in diese Basis-Einheit. (Ähnlich dem ppm-Format bei Bildern, welches ImageMagicks convert nutzt)

Ok, bei 3 Einheiten gewinnt man nicht wirklich etwas, aber kommen noch mehr hinzu, wird es einfacher :-)

Desweiteren wäre eine einzige convert-Funktion eine Überlegung wert, die anhand eines Musters die Konvertierung vornimmt:

Code: Alles auswählen

def convert(value, method="c->k"):
    # mapping von einheit in kelvin
    to_kelvin = {
        "c": c2k,
        # usw.
    }
    # mapping von kelvin in einheit
    from_kelvin = {
        "c": k2c
    }
    # jetzt method aufsplitten und funktionen aus dem mapping callen
    #Wert zurückgeben
Alternativ könnte man auch eine Temperatur-Klasse erstellen, die ähnlich dem Unicode -> Byte Konzept arbeitet. Sprich man muss eine Art "encoding" und "decoding" angeben beim Setzen bzw. Auslesen, wenn man eine andere Einheit haben will als Kelvin.

Code: Alles auswählen

>>> tmp = Temperature(42.5).decode("c")
"278k"
>>> tmp.encode("f")
"xyzf"
Man kann also auch aus einem kleinen Projekt interessante Dinge basteln :-)
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

@Hyperion, höhrt sich gut an

Hab die Liste mal erweitert

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-

from __future__ import division

def f2c(fahrenheit):
    return (fahrenheit - 32) * 5 / 9

def c2f(celsius):
    return 9/5 * celsius + 32

def c2k(celsius):
    return celsius + 273.15

def k2c(kelvin):
    return kelvin - 273.15

def c2re(celsius):
    return celsius * 0.8

def re2c(reaumur):
    return reaumur * 1.25

def c2n(celsius):
    return celsius * 0.33

def n2c(newton):
    return newton / 0.33

def c2ra(celsius):
    return celsius * 1.8 + 32 + 459.67

def ra2c(rankine):
    return (rankine - 32 - 459.67) / 1.8

def c2ro(celsius):
    return celsius * 21 / 40 + 7.5

def ro2c(romer):
    return ((romer - 7.5) * 40) / 21

def c2d(celsius):
    return (100 - celsius) * 1.5

def d2c(delisle):
    return 100 - delisle * 2 / 3

if __name__ == '__main__':
    print 'f2c: ° Celsius:', f2c(77)
    print 'c2f: ° Fahrenheit:', c2f(-43)
    print 'c2k: ° Kelvin:', c2k(0)
    print 'c2r: ° Réaumur:', c2re(1)
    print 'c2n: ° Newton:', c2n(16)
@Hyperion zum 2.: Deine Idee mit der Klasse werd ich mal umsetzten.
the more they change the more they stay the same
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

Langsam wird es ohne Docstrings etwas unübersichtlich. Außerdem heißt es ``Kelvin`` und nicht ``° Kelvin``.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Klar Kelvin statt ° Kelvin, Doc-Strings gibts in der Klasse dann
the more they change the more they stay the same
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Der "Grad-Rechner" jetzt in einer Klasse mit "decode" und "encode"

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-

from __future__ import division, print_function

class TemperatureError(Exception):
    def __init__(self, val):
        self.val = val
    def __str__(self):
        return repr(self.val)

class TemperatureDecodeError(Exception):
    def __init__(self, val):
        self.val = val
    def __str__(self):
        return repr(self.val)

class TemperatureEncodeError(Exception):
    def __init__(self, val):
        self.val = val
    def __str__(self):
        return repr(self.val)


class Temperature(object):
    def __init__(self, temp, base='k'):
        try:
            self.temp = float(temp)
        except TypeError:
            raise TemperatureError('Temperature must be integer or float')
        self.base = base
        
        self.decode_units = {'c' : self.c2k, 'f' : self.f2k, 're' : self.re2k, 'n' : self.n2k, 'ra' : self.ra2k,
                             'ro' : self.ro2k, 'd' : self.d2k}
        self.encode_units = {'c' : self.k2c, 'f' : self.k2f, 're' : self.k2re, 'n' : self.k2n, 'ra' : self.k2ra,
                             'ro' : self.k2ro, 'd' : self.k2d}
        
    def __str__(self):
        '''returns the temperature as a string'''
        return str(self.temp)
    def __int__(self):
        '''returns the temperature rounded as an integer'''
        return int(round(self.temp, 0))
    def __float__(self):
        '''returns the temperature as a float'''
        return float(self.temp)

    def decode(self, unit=''):
        '''converts a temperature to Kelvin'''
        try:
            if self.decode_units.has_key(unit):
                self.temp = self.decode_units[unit](self.temp)    
                return self.temp
            elif not unit:
                raise TemperatureDecodeError('encode expected at least 1 argument, got 0')
            else:
                error = 'unknown unit: {0}'.format(unit)
                raise LookupError(error)
        except TypeError:
            raise TemperatureDecodeError('decode argument must be string not {0}'.format(unit.__class__.__name__))
    def encode(self, unit=''):
        '''converts a temperature to the given unit'''
        try:
            if self.decode_units.has_key(unit):
                self.temp = self.encode_units[unit](self.temp)
                return self.temp
            elif not unit:
                raise TemperatureEncodeError('encode expected at least 1 argument, got 0')
            else:
                error = 'unknown unit: {0}'.format(unit)
                raise LookupError(error)
        except TypeError:
            raise TemperatureEncodeError('decode argument must be string not {0}'.format(unit.__class__.__name__))

    ### Celsius
    def c2k(self, celsius):
        '''converts °Celsius to Kelvin'''
        return celsius + 273.15
    def k2c(self, kelvin):
        '''converts Kelvin to °Celsius'''
        return kelvin - 273.15
    ### Fahrenheit
    def f2k(self, fahrenheit):
        '''converts °Fahrenheit to Kelvin'''
        return (fahrenheit + 459.67) * 5 / 9
    def k2f(self, kelvin):
        '''converts Kelvin to °Fahrenheit'''
        return kelvin * 1.8 - 459.67
    ### Réaumur
    def re2k(self, reamur):
        '''converts °Réaumur to Kelvin'''
        return reamur * 1.25 + 273.15
    def k2re(self, kelvin):
        '''converts Kelvin to Réaumur'''
        return (kelvin - 273.15) * 0.8
    ### Newton
    def n2k(self, newton):
        '''converts °Newton to Kelvin'''
        return newton / 0.33 + 273.15
    def k2n(self, kelvin):
        '''converts Kelvin to °Newton'''
        return (kelvin - 273.15) * 0.33
    ### Rankine
    def ra2k(self, rankine):
        '''converts °Rankine to Kelvin'''
        return rankine / 1.8
    def k2ra(self, kelvin):
        '''converts Kelvin to °Rankine'''
        return kelvin * 1.8
    ### Rømer
    def ro2k(self, romer):
        '''converts °Rømer to Kelvin'''
        return ((romer - 7.5) * 40) / 21 + 273.15
    def k2ro(self, kelvin):
        '''converts Kelvin to Rømer'''
        return (kelvin - 273.15) * 21 / 40 + 7.5 
    ### Delisle
    def d2k(self, delisle):
        '''converts °Delisle to Kelvin'''
        return 373.15 - delisle * 2 / 3
    def k2d(self, kelvin):
        '''converts Kelvin to °Delisle'''
        return (373.15 - kelvin)  * 1.5
    

if __name__ == '__main__':
    x = Temperature(-272.15)
    x.decode('c')
    for key in x.encode_units:
        print(key, x.encode(key))
        print(key, x.decode(key))
        print('-' * 15)
the more they change the more they stay the same
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Also irgendwie finde ich die ganzen Methoden schon ziemlich doof. Ich finde dass sie arg viel Overhead sind und die Umrechnungstabellen eher Daten und nicht Code sind (natürlich, Lisp lehrt uns Code == Data, aber in dem Fall wäre eine Datenstruktur IMHO besser).
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Whitie
User
Beiträge: 216
Registriert: Sonntag 4. Juni 2006, 12:39
Wohnort: Schulzendorf

Hallo Dav1d,
ich hatte sowas mal für die Arbeit zusammengebastelt:

http://paste.pocoo.org/show/153448/

Kurz und hatte für meine Zwecke soweit funktioniert.

Gruß
Whitie
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Danke Whitie, das mit den "lambdas" is ne gute Idee, ich glaub die übernimm ich ;)

Wenn ichs hab kommts hier rein ;)

//Edit: Jetzt ist es so weit:

Mit self.unit und self.base bzw. base (als Parameter), will ich noch was tolles machen ;)

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-

from __future__ import print_function, division

class TemperatureError(Exception):
    def __init__(self, val):
        self.val = val
    def __str__(self):
        return repr(self.val)

class TemperatureDecodeError(Exception):
    def __init__(self, val):
        self.val = val
    def __str__(self):
        return repr(self.val)

class TemperatureEncodeError(Exception):
    def __init__(self, val):
        self.val = val
    def __str__(self):
        return repr(self.val)


class Temperature(object):
    def __init__(self, temp, base='k'):
        try:
            self.temp = float(temp)
        except TypeError:
            raise TemperatureError('Temperature must be integer or float')
        self.base = base
        self.unit = None
                
        self.decode_units = {'c' : lambda x: x + 273.15, # converts °Celsius to Kelvin
                             'f' : lambda x: (x + 459.67) * 5 / 9, # converts °Fahrenheit to Kelvin
                             're' : lambda x: x * 1.25 + 273.15, # converts °Réaumur to Kelvin 
                             'n' : lambda x: x / 0.33 + 273.15, # converts °Newton to Kelvin
                             'ra' : lambda x: x / 1.8, # converts °Rankine to Kelvin
                             'ro' : lambda x: ((x - 7.5) * 40) / 21 + 273.15, # converts °Rømer to Kelvin
                             'd' : lambda x: 373.15 - x * 2 / 3 # converts °Delisle to Kelvin
                             }
        
        self.encode_units = {'c' : lambda x: x - 273.15, # converts Kelvin to °Celsius
                             'f' : lambda x: x * 1.8 - 459.67, # converts Kelvin to °Fahrenheit
                             're' : lambda x: (x - 273.15) * 0.8, # converts °Réaumur to Kelvin
                             'n' : lambda x: (x - 273.15) * 0.33, # converts Kelvin to °Newton
                             'ra' : lambda x: x * 1.8, # converts Kelvin to °Rankine
                             'ro' : lambda x: (x - 273.15) * 21 / 40 + 7.5, # converts Kelvin to °Rømer
                             'd' : lambda x: (373.15 - x)  * 1.5 # converts Kelvin to °Delisle
                             }
        
    def __str__(self):
        '''returns the temperature as a string'''
        return str(self.temp)
    def __int__(self):
        '''returns the temperature rounded as an integer'''
        return int(round(self.temp, 0))
    def __float__(self):
        '''returns the temperature as a float'''
        return float(self.temp)
    
    def __repr__(self):
        return '<Temperature{0!r}>'.format(self.temp)

    def decode(self, unit=''):
        '''converts a temperature to Kelvin'''
        try:
            if self.decode_units.has_key(unit):
                self.temp = self.decode_units[unit](self.temp)
                if self.temp < 0:
                    error = 'Kelvin can\'t be negativ, ({0} K)'.format(self.temp)
                    raise TemperatureError(error)
                self.unit = 'k'
                return self.temp
            elif not unit:
                raise TemperatureDecodeError('encode expected at least 1 argument, got 0')
            else:
                error = 'unknown unit: {0}'.format(unit)
                raise LookupError(error)
        except TypeError:
            raise TemperatureDecodeError('decode argument must be string not {0}'.format(unit.__class__.__name__))
    def encode(self, unit=''):
        '''converts a temperature to the given unit'''
        try:
            if self.decode_units.has_key(unit):
                self.temp = self.encode_units[unit](self.temp)
                self.unit = unit
                return self.temp
            elif not unit:
                raise TemperatureEncodeError('encode expected at least 1 argument, got 0')
            else:
                error = 'unknown unit: {0}'.format(unit)
                raise LookupError(error)
        except TypeError:
            raise TemperatureEncodeError('decode argument must be string not {0}'.format(unit.__class__.__name__))
    

if __name__ == '__main__':
    x = Temperature(-272.15)
    x.decode('c')
    for key in x.encode_units:
        print(key, x.encode(key))
        print(key, x.decode(key))
        print('-' * 15)
the more they change the more they stay the same
crs
User
Beiträge: 42
Registriert: Dienstag 14. Juli 2009, 13:24

im grunde sind selbst die ganzen lambda funktionen redundant ;)
die umrechenfunktionen sind ja alle linear, deswegen koennte man auch nur die beiden koeffizienten speichern. also in etwa sowas:

Code: Alles auswählen

units = { c : (1, 273.15),
          f : (5.0/9, 5*459.67/9),
          ...
}

def f(a, b):
    return lambda x: a*x+b

print '42 Grad Celsius -> Kelvin: %s' % f(*units[c])(42)
aber ob das wirklich uebersichtlicher waere...
Zuletzt geändert von crs am Samstag 28. November 2009, 17:44, insgesamt 1-mal geändert.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

crs hat geschrieben:aber ob das wirklich uebersichtlicher waere...
Wenn man das Beispiel noch umbaut, dass man ganz auf "lambda" verzichtet, fände ich das auf jeden Fall besser.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Ich glaube nicht, aber auf jeden Fall schwerer zu verstehen

//Edit: @ice2k3, ich wüsste nicht wie
the more they change the more they stay the same
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Code: Alles auswählen

units = { 'c' : (1, 273.15),
          'f' : (5.0/9, 5*459.67/9)
}

def f(x, a, b):
    return a*x+b

print '42 Grad Celsius -> Kelvin: %s' % f(42, *units['c']) 
Edit: Kleine Korrekturen
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Das funktioniert aber nicht bei allen Grad-Maßen

z.B.:

Code: Alles auswählen

'd' : lambda x: 373.15 - x * 2 / 3 # converts °Delisle to Kelvin
the more they change the more they stay the same
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Code: Alles auswählen

units = { 'd' : (-2/3.0, 373.15),
         ...
}
Wieso soll das nicht funktionieren?!
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

ok soweit hab ich nicht gedacht, ich werd mich mal dran setzten
the more they change the more they stay the same
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Den "Grad-Berechner" gibts jetzt auch Online: Grad-Berechner Online

//Edit: Verzeiht mir Bugs etc. mein 1. Python-Skript im Internet

//Edit²: neue URL: Grad-Konverter
Zuletzt geändert von Dav1d am Montag 30. November 2009, 15:54, insgesamt 1-mal geändert.
the more they change the more they stay the same
Antworten