11
\$\begingroup\$

I am currently creating a program that can convert different units of measurement for temperature. It includes conversions for Celsius, Fahrenheit, kelvin and gas mark. Can someone tell me how I could make my code simpler so I can add more units of temperature measurement (e.g. Rankine). Also, is there any way to stop having to use big spaces in my input quotes to get them line by line?

print ("Welcome to the temperature converter, please choose which measurement you want to convert TO")
print (" ")
which = input("If you want to convert TO a fahrenheit value, press f.                                         If you want to convert TO a celcius value, press c.                                  If you want to convert TO a kelvin value, press k.                                   If you want to convert TO a gas mark value, press g.")
if which == "f":
 print (" ")
 print ("Now choose the measurement you are converting FROM")
 fwhich = input("If you want to convert FROM a celcius value, press c.                                 If you want to convert FROM a kelvin value press k.                                    If you want to convert FROM a gas mark value, press g.")
 if fwhich == "c":
  print (" ")
  celcius = float(input("Input the celcius value: "))
  fahrenheit = (celcius*(9/5)+32)
  print ("In fahrenheit, this is " , fahrenheit)
 elif fwhich == "k":
  print (" ")
  kelvin = float(input("Input the kelvin value: "))
  fahrenheit = (1.8 * (kelvin - 273) + 32)
  print ("In fahrenheit, this is " , fahrenheit)
 elif fwhich == "g":
  print (" ")
  gasmark = float(input("Input the gas mark value: "))
  fahrenheit = 250 + (gasmark * 25)
  print ("In fahrenheit, this is " , fahrenheit)
 else:
  print (" ")
  print ("Error, you didn't enter any of the specified keys")
elif which == "c":
 print (" ")
 print ("Now choose the measurement you are converting FROM")
 cwhich = input("If you want to convert FROM a fahrenheit value, press f.                               If you want to convert FROM a kelvin value, press k.                                 If you want to convert FROM a gas mark value, press g.")
 if cwhich == "f":
  print (" ")
  fahrenheit = float(input("Input the fahrenheit value: "))
  celcius = (fahrenheit - 32)*(5/9)
  print ("In celcius, this is " , celcius)
 elif cwhich == "k":
  print (" ")
  kelvin = float(input("Input the kelvin value: "))
  celcius = kelvin - 273
  print ("In celcius, this is " , celcius)
 elif cwhich == "g":
  print (" ")
  gasmark = float(input("Input the gas mark value: "))
  celcius = 130 + (gasmark * 10)
 else:
  print (" ")
  print ("Error, you didn't enter any of the specified keys")
elif which == "k":
 print (" ")
 print ("Now choose the measurement you are converting FROM")
 kwhich = input("If you want to convert FROM a fahrenheit value, press f.                               If you want to convert FROM a celcius value, press c.                                 If you want to convert FROM a gas mark value, press g.")
 if kwhich == "f":
  print (" ")
  fahrenheit = float(input("Input the fahrenheit value: "))
  kelvin = ((5/9) * (fahrenheit - 32) + 273)
  print ("In kelvin, this is " , kelvin)
 elif kwhich == "c":
  print (" ")
  celcius = float(input("Input the celcius value: "))
  kelvin = (celcius + 273)
  print ("In kelvin, this is " , kelvin)
 elif kwhich == "g":
  print (" ")
  gasmark = float(input("Input the gas mark value: "))
  kelvin = ((130 + (gasmark * 10))+ 273)
  print ("In kelvin, this is " , kelvin)
 else:
  print (" ")
  print ("Error, you didn't enter any of the specified keys")
elif which == "g":
 print (" ")
 print ("Now choose the measurement you are converting FROM")
 gwhich = input("If you want to convert FROM a fahrenheit value, press f.                               If you want to convert FROM a celcius value, press c.                                 If you want to convert FROM a kelvin value, press k.")
 if gwhich == "f":
  print (" ")
  fahrenheit = float(input("Input the fahrenheit value: "))
  gasmark = (fahrenheit / 25) - 10
  print ("In gas mark, this is " , gasmark)
 elif gwhich == "c":
  print (" ")
  celcius = float(input("Input the celcius value: "))
  gasmark = ((celcius / 10) -13)
  print ("In gas mark, this is " , gasmark)
 elif gwhich == "k":
  print (" ")
  kelvin = float(input("Input the kelvin value: "))
  gasmark = (((kelvin - 273) / 10) -13) 
  print ("In gas mark, this is " , gasmark)
 else:
  print (" ")
  print ("Error, you didn't enter any of the specified keys")
else:
 print (" ")
 print ("Error, you didn't enter any of the specified keys")
\$\endgroup\$
  • 7
    \$\begingroup\$ A small bit of pedantry - in physics, "heat" is something different to "temperature"; it's jarring to see the terms used interchangeably like that! \$\endgroup\$ – Toby Speight Mar 29 '17 at 13:26
  • \$\begingroup\$ @TobySpeight fixed it, was annoying me as well :) \$\endgroup\$ – Graipher Mar 29 '17 at 14:03
  • 5
    \$\begingroup\$ I think it's not that useful to post work from the absolute beginning of a programming education on Code Review. Either you'll get an answer that's much too advanced or people will adapt their solutions to okayish compromises suited to your level — the first doesn't help much and the second isn't really the purpose of the site. I would bring this to an instructor to learn the basics on a suitable curve. \$\endgroup\$ – Luke Sawczak Mar 29 '17 at 15:32
  • \$\begingroup\$ Reminds me of codereview.stackexchange.com/questions/157958/… \$\endgroup\$ – ilkkachu Mar 29 '17 at 15:39
10
\$\begingroup\$

First of all, Python has an official style-guide, PEP8. It recommends using 4 spaces as indentation, instead of 1, which makes code a lot easier to read.

Second, you should follow the single responsibility principle and define functions that do one thing, instead of having one large bunch of code.

For temperature conversion, it makes sense to first convert to one base unit (Kelvin is the obvious choice for temperature, but you might also go for Rankine if you really want to). This way you don't have to define all conversions from all units to all other units, just to and from the base unit.

Here is a start:

def temperature_C_to_K(temp_C):
    return temp_C + 273.15

def temperature_K_to_C(temp_K):
    return temp_K - 273.15

def temperature_F_to_K(temp_F):
    return 5./9 * (temp_F - 32) + 273.15

def temperature_K_to_F(temp_K):
    return 1.8 * (temp_K - 273.15) + 32

to_K_from = {"c": temperature_C_to_K,
             "f": temperature_F_to_K,
             "k": lambda t: t}
from_K_to = {"c": temperature_K_to_C,
             "f": temperature_K_to_F,
             "k": lambda t: t}

if __name__ == "__main__":
    kelvin = to_K_from["c"]
    fahrenheit = from_K_to["f"]
    temperature = 33
    print(fahrenheit(kelvin(temperature)))

With the additional dictionaries I defined, you can now get the user input for the to and from temperature and use these functions:

from_unit = input("From which unit? ").lower()
temperature = float(input("What temperature in that unit? "))
to_unit = input("Convert to which unit? ").lower()
print(from_K_to[to_unit](to_K_from[from_unit](temperature)))

This has no real input validation so far, so if the user entered a string for the temperature it would raise an exception and it also does not advertise which units are available, but this is left up to you.

You could even define another function for that last, complicated looking, bit:

def convert(temperature, from_unit, to_unit):
    return from_K_to[to_unit](to_K_from[from_unit](temperature))
\$\endgroup\$
16
\$\begingroup\$

The biggest problem with your code is the amount of repetition. You can reduce this by defining a Unit class:

class Unit(object):
    "A temperature unit that can be linearly converted to or from Kelvins."
    def __init__(self, name, slope, intercept):
        self.name = name
        self.slope = slope
        self.intercept = intercept

    def to_kelvins(self, t):
        return self.intercept + t / self.slope

    def from_kelvins(self, k):
        return (k - self.intercept) * self.slope

We can now create a dictionary of units, keyed by the single letter that the user will select them by:

all_units = {
    "k": Unit("kelvins", 1.0, 0.0),
    "c": Unit("Celsius", 1.0, 273.15),
    "r": Unit("rankin", 9.0/5, 0.0),
    "f": Unit("Fahrenheit", 9.0/5, 255.37),
    "g": Unit("Gas Mark", 9.0/125, 255.37+250*5.0/9),
}

Let's make a quick test of the above:

if __name__ == '__main__':
    for i in [0, 255.37, 273.15, 373.15, 473.15]:
        for unit in all_units.values():
            print("%.2f K is %.2f %s" % (i, unit.from_kelvins(i), unit.name))
        print()

This produces the output we expect:

0.00 K is 0.00 kelvins
0.00 K is -273.15 Celsius
0.00 K is 0.00 rankin
0.00 K is -28.39 Gas Mark
0.00 K is -459.67 Fahrenheit

255.37 K is 255.37 kelvins
255.37 K is -17.78 Celsius
255.37 K is 459.67 rankin
255.37 K is -10.00 Gas Mark
255.37 K is 0.00 Fahrenheit

273.15 K is 273.15 kelvins
273.15 K is 0.00 Celsius
273.15 K is 491.67 rankin
273.15 K is -8.72 Gas Mark
273.15 K is 32.00 Fahrenheit

373.15 K is 373.15 kelvins
373.15 K is 100.00 Celsius
373.15 K is 671.67 rankin
373.15 K is -1.52 Gas Mark
373.15 K is 212.00 Fahrenheit

473.15 K is 473.15 kelvins
473.15 K is 200.00 Celsius
473.15 K is 851.67 rankin
473.15 K is 5.68 Gas Mark
473.15 K is 392.00 Fahrenheit

Now we can work on the input and output. This needs to choose an input unit and value. Given that, we can compute the (Kelvin) temperature in question using input_unit.to_kelvin(). When the user chooses an output unit, we can use output_unit.from_kelvin() to calculate the result:

if __name__ == '__main__':
     # N.B. all error-checking is left as an exercise
    input_unit = all_units[input("From which unit? ")]
    input_value = float(input("What temperature, in %s? " % input_unit.name))
    kelvin_temp = input_unit.to_kelvins(input_value)
    output_unit = all_units[input("To which unit? ")]
    output_value = output_unit.from_kelvins(kelvin_temp)
    print("%.2f %s is %.2f %s" % (input_value, input_unit.name, output_value, output_unit.name))
\$\endgroup\$
  • \$\begingroup\$ Nice class. Fortunately all temperature scales I know actually are just a linear transformation of any other scale :) \$\endgroup\$ – Graipher Mar 29 '17 at 14:10
  • 1
    \$\begingroup\$ Me too - here's a nice chart with some ideas for more units to add (you'll need a negative slope value for Delisle). \$\endgroup\$ – Toby Speight Mar 29 '17 at 14:20
1
\$\begingroup\$

I would suggest you download PyCharm to write your code. It automatically tells you about the standard python syntax, also, instead of having huge spaces by using 'input()', try using Console.writeline() and Console.readline() {readline or writeline both add newlines at the end}

Also, as Mr. Speight suggested, using classes is the way to go. Cheers!

\$\endgroup\$
  • \$\begingroup\$ This seems more like a comment than a full review/answer... \$\endgroup\$ – Thomas Ward Mar 30 '17 at 23:05
  • \$\begingroup\$ Sorry can't comment yet, will change this as soon as I can. \$\endgroup\$ – BikerDude Mar 31 '17 at 18:19
0
\$\begingroup\$

Thank you everyone, I have re-written my code to now include every temperature unit I can find (if there are more tell me). Here is my new code:

import sys
print ("Welcome to the temperature converter, please enter the unit you wish to convert FROM:")
print ("")
FROM = input("Type 'celcius', 'fahrenheit', 'kelvin', 'gas mark', 'rankine', 'delisle', 'newton', 'reaumur' or 'romer'").lower()
if FROM == "celcius" or FROM == "fahrenheit" or FROM == "kelvin" or FROM == "gas mark" or FROM == "rankine" or FROM == "delisle" or FROM == "newton" or FROM == "reaumur" or FROM == "romer": 
    print ("")
    VALUE = int(input("Now input the temperature in that unit"))
    if FROM == "celcius":
        kelvin = (VALUE + 273)
    elif FROM == "fahrenheit":
        kelvin = ((5/9) * (VALUE - 32) + 273)
    elif FROM == "kelvin":
        kelvin = VALUE
    elif FROM == "gas mark":
        kelvin = ((130 + (VALUE * 10))+ 273)
    elif FROM == "rankine":
        kelvin = (VALUE * (5/9))
    elif FROM == "delisle":
        kelvin = (373 - (VALUE * (2/3)))
    elif FROM == "newton":
        kelvin = (VALUE * (100/33) + 273) 
    elif FROM == "reaumur":
        kelvin = (VALUE * (5/4) + 273)
    elif FROM == "romer":
        kelvin = ((VALUE - 7.5) * (40/21) + 273)
else:
    print("")
    print ("You did not enter any of the specified words")
    sys.exit(1)
print ("")
TO = input("Now input the unit you wish to convert TO: Type 'celcius', 'fahrenheit', 'kelvin', 'gas mark', 'rankine', 'delisle', 'newton', 'reaumur' or 'romer'").lower()
if TO == "celcius" or TO == "fahrenheit" or TO == "kelvin" or TO == "gas mark" or TO == "rankine" or TO == "delisle" or TO == "newton" or TO == "reaumur" or TO == "romer":
    print ("")
    if TO == "celcius":
        END = (kelvin - 273)
    elif TO == "fahrenheit":
        END = (1.8 * (kelvin - 273) + 32)
    elif TO == "kelvin":
        END = kelvin
    elif TO == "gas mark":
        END = (((kelvin - 273) / 10) -13) 
    elif TO == "rankine":
        END = (kelvin * (9/5))
    elif TO == "delisle":
        END = ((373 - kelvin) * (3/2))
    elif TO == "newton":
        END = ((kelvin - 273) * (33/100))
    elif TO == "reaumur":
        END = ((kelvin - 273) * (4/5)) 
    elif TO == "romer":
        END = ((kelvin - 273) * (21/40) + 7.5)
else:
    print ("")
    print ("You did not enter any of the specified words")
    sys.exit(1)

print ("Your" ,  FROM , "value of" , VALUE , ", is" , END , "in" , TO )
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.