-3

When I run the program and put in the values 3, 1, 1 so convert one cup to tablespoons, it uses the TOtbsp function at the bottom. For troubleshooting purposes, I've made it print out four variables before the final result. These variables all print out the correct results,

def TOtbsp ():
    os.system('cls')
    print ('Convert ' + convFROMconv + ' to: tablespoons')
    dictEnt = dCallOne['tbsp']
    print (dCallOne['tbsp'])
    print (dCallOne)
    print (dictEnt)
    print (convFactor)
    calc = convFactor * dictEnt
    print(calc)

^That's the TOtbsp function, what comes out is this:

Convert Cups to: tablespoons

16
{'tbsp': 16, 'tsp': 48, 'quart': 0.25, 'floz': 8.32674, 'pint':0.5,'gal':0.0625, 'ml': 236.588, 'liter': 0.236588}
16
1
1111111111111111

These are all correct, except the final one, calc. I've tried setting it up a few different ways:

calc = convFactor * dictEnt
calc = (convFactor * dictEnt)
calc = (convFactor * dCallOne['tbsp'])
calc = (convFactor * (dCallOne['tbsp'])
(convFactor * dictEnt) = calc
(convFactor * (dCallOne['tbsp']) = calc
convFactor * dictEnt = calc
(convFactor * dCallOne['tbsp']) = calc

As far as I know, all of these, excapt maybe the bottom four, should get the correct answer because both convFactor, dictEnt, and dCallOne all get integers.

The full code is below.

import os

tbsp = {'tbsp' : 1 ,
        'cup' : 0.0625 ,
        'tsp' : 3 ,
        'quart' : 0.015625 ,
        'floz' : 0.5 ,
        'pint' : 0.03125 ,
        'gal' : 0.00390625 ,
        'ml' : 14.7868 ,
        'liter' : 0.0147868}
tsp = {'cup' : 0.0208333 , 'tbsp' : 0.333333 , 'quart' : 0.0052083333 , 'floz' : 0.1666666667 , 'pint' :  0.0104166667, 'gal' : 0.00130208323 , 'ml' : 4.92892 , 'liter' : 0.00492892}
dictcups = cups = {'tbsp' : 16 ,
        'tsp' : 48 ,
        'quart' : 0.25 ,
        'floz' : 8.32674 ,
        'pint' : 0.5 ,
        'gal' : 0.0625 ,
        'ml' : 236.588 ,
        'liter' : 0.236588}
quart = {'cup' : 4 , 'tsp' : 192 , 'tbsp' : 64 , 'floz' : 32 , 'pint' : 2 , 'gal' : 0.25 , 'ml' : 946.353 , 'liter' : 0.946353}
floz = {'cup' : 0.125 , 'tsp' : 6 , 'quart' : 0.03125 , 'tbsp' : 2 , 'pint' : 0.0625 , 'gal' : 0.0078125 , 'ml' : 29.5735 , 'liter' : 0.0295735}
pint = {'cup' : 2 , 'tsp' : 96 , 'quart' : 0.5 , 'floz' : 16 , 'tbsp' : 32 , 'gal' : 0.125 , 'ml' : 473.176 , 'liter' : 0.473176}
gal = {'cup' : 16 , 'tsp' : 768 , 'quart' : 4 , 'floz' : 128 , 'pint' : 8 , 'tbsp' : 256 , 'ml' : 3785.41 , 'liter' : 3.78541}
ml = {'cup' : 0.0042267571 , 'tsp' : 0.202884 , 'quart' : 0.00105669 , 'floz' : 0.033814 , 'pint' : 0.00211338 , 'gal' : 0.000264172 , 'tbsp' : 0.067628 , 'liter' : 0.001}
liter = {'cup' : 4.226757063 , 'tsp' : 202.884 , 'quart' : 1.05669 , 'floz' : 33.814 , 'pint' : 2.11338 , 'gal' : 0.264172 , 'ml' : 1000 , 'tbsp' : 67.628}
acceptableInputs = ['1', '2', '3', '4', '5', '6', '7', '8', '9'] #This is used to check if what the user entered is one of the eight acceptable units

def takeUnit1 (): #Figure out what unit the user wants to convert
    global convFactor
    print ('Unit Converter')
    print ('')
    print ('')
    print ('Select the unit you want to convert FROM')
    print ('')
    print ('1 Tbsp - Tablespoon')
    print ('2 Tsp - Teaspoon')
    print ('3 C - Cups')
    print ('4 qt. - Quart')
    print ('5 fl. oz. - Fluid Ounce')
    print ('6 gal. - Gallon')
    print ('7 ml - Milliliter')
    print ('8 L - Liter')
    print ('9 P - Pints')
    convFROM = input('Unit: ')
    convFactor = input('How many?: ')

    if convFROM in acceptableInputs: #Check if input is acceptable
        global convFROMconv
        global dCallOne
        if convFROM == '1':
            convFROMconv = 'Tablespoons'
            dCallOne = tbsp
            takeUnit2()  # Run the function to figure out what unit to convert to

        elif convFROM == '2':
            convFROMconv = 'Teaspoons'
            dCallOne = tsp
            takeUnit2()  # Run the function to figure out what unit to convert to

        elif convFROM == '3':
            convFROMconv = 'Cups'
            dCallOne = dictcups
            takeUnit2()  # Run the function to figure out what unit to convert to

        elif convFROM == '4':
            convFROMconv = 'Quarts'
            dCallOne = quart
            takeUnit2()  # Run the function to figure out what unit to convert to

        elif convFROM == '5':
            convFROMconv = 'Fluid Ounces'
            dCallOne = floz
            takeUnit2()  # Run the function to figure out what unit to convert to

        elif convFROM == '6':
            convFROMconv = 'Gallons'
            dCallOne = gal
            takeUnit2()  # Run the function to figure out what unit to convert to

        elif convFROM == '7':
            convFROMconv = 'Milliliters'
            dCallOne = ml
            takeUnit2()  # Run the function to figure out what unit to convert to

        elif convFROM == '8':
            convFROMconv = 'Liters'
            dCallOne = liter
            takeUnit2()  # Run the function to figure out what unit to convert to

        elif convFROM == '9':
            convFROMconv = 'Pints'
            dCallOne = pint
            takeUnit2()  # Run the function to figure out what unit to convert to

        else:
            print ('')

    else:
        print('That is not an acceptable input, please try again')


def takeUnit2 (): #This function is to figure out what unit the user wants to convert TO
    os.system('cls')
    print ('Select the unit you want to convert TO')
    print ('1 Tbsp - Tablespoon')
    print ('2 Tsp - Teaspoon')
    print ('3 C - Cups')
    print ('4 qt. - Quart')
    print ('5 fl. oz. - Fluid Ounce')
    print ('6 gal. - Gallon')
    print ('7 ml - Milliliter')
    print ('8 L - Liter')
    print ('9 P - Pints')
    convTO = input('Unit: ')

    if convTO in acceptableInputs: #Checking if it is one of the 8 accepted units
        global convTOname #Making convTOconv global
        global TOfunc1
        if convTO == '1': #This whole statement converts the input number to its corresponding name
            convTOname = 'tbsp'
            TOfunc1 = 'TOtbsp'
            TOtbsp()

        elif convTO == '2':
            convTOname = 'tsp'
            TOfunc1 = 'TOtsp'
            TOtsp()

        elif convTO == '3':
            convTOname = 'cup'
            TOfunc1 = 'TOcups'
            TOcup()

        elif convTO == '4':
            convTOname = 'quart'
            TOfunc1 = 'TOquarts'
            TOquart()

        elif convTO == '5':
            convTOname = 'floz'
            TOfunc1 = 'TOfloz'
            TOfloz()

        elif convTO == '6':
            convTOname = 'gal'
            TOfunc1 = 'TOgal'
            TOgal()

        elif convTO == '7':
            convTOname = 'ml'
            TOfunc1 = 'TOml'
            TOml()

        elif convTO == '8':
            convTOname = 'liter'
            TOfunc1 = 'TOliters'
            TOliter()

        elif convTO == '9':
            convTOname = 'pint'
            TOfunc1 = 'TOpint'
            TOpint()


        else: #Statement requires an else, not intended to ever be used
            print ('')

    else:
        print('That is not an acceptable input, please try again')


def TOtbsp ():
    os.system('cls')
    print ('Convert ' + convFROMconv + ' to: tablespoons')
    dictEnt = dCallOne['tbsp']
    print (dCallOne['tbsp'])
    print (dCallOne)
    print (dictEnt)
    print (convFactor)
    calc = convFactor * dictEnt
    print(calc)

def TOtsp ():
    os.system('cls')
    print ('Convert ' + convFROMconv + ' to: teaspoons')
    print (dCallOne)
    calc = dCallOne['tsp']
    print(calc)

def TOcup ():
    os.system('cls')
    print ('Convert ' + convFROMconv + ' to: cups')
    print (dCallOne)
    calc = dCallOne['cup']
    print(calc)

def TOquart ():
    os.system('cls')
    print ('Convert ' + convFROMconv + ' to: quarts')
    print (dCallOne)
    calc = dCallOne['quart']
    print(calc)

def TOfloz ():
    os.system('cls')
    print ('Convert ' + convFROMconv + ' to: fluid ounces')
    print (dCallOne)
    calc = dCallOne['floz']
    print(calc)

def TOml ():
    os.system('cls')
    print ('Convert ' + convFROMconv + ' to: milliliters')
    print (dCallOne)
    calc = dCallOne['ml']
    print(calc)

def TOgal ():
    os.system('cls')
    print ('Convert ' + convFROMconv + ' to: gallons')
    print (dCallOne)
    calc = dCallOne['gal']
    print(calc)


def TOpint ():
    os.system('cls')
    print ('Convert ' + convFROMconv + ' to: pints')
    print (dCallOne)
    calc = dCallOne['pint']
    print(calc)

def TOliter ():
    os.system('cls')
    print ('Convert ' + convFROMconv + ' to: liters')
    print (dCallOne)
    calc = dCallOne['liter']
    print(calc)

takeUnit1()
  • Unclear. "These are all correct, except the final one" - What exactly is not correct? Say something like "I expected to get 1234 because (insert reason) but I got 4567 instead." – Brandin Mar 12 '17 at 10:47

2 Answers2

2

In Python 3, input() returns a string (even if the user enters a number), and so convFactor = input('How many?: ') will set the value of convFactor to a string. Multiplying a string by a number (as happens in calc = convFactor * dictEnt) simply repeats the string that many times, and so you end up with sixteen 1's. To fix this, use int() to convert convFactor to a number, ideally right after the call to input():

convFactor = int(input('How many?: '))
jwodder
  • 54,758
  • 12
  • 108
  • 124
1

jwodder has answered your question: you need to convert input strings to numbers if you want to perform arithmetic with them. You can do the conversion with int(), but it's better to use float(): that lets the user input decimal numbers.

However, your program has a lot of repetition. This is not good design. It makes the program longer than it needs to be, and it makes it harder to read and maintain. Readers have to figure out which bits are supposed to be identical, and which bits are supposed to be different. And when you want to make modifications you have to replicate the modifications to multiple places, which is tedious and error-prone. Please see the Wikipedia article Don't repeat yourself.

Here's a more compact version of your program. The main change I made is to put all the separate conversion ratio dictionaries into a dictionary of dictionaries. I use a loop to display the menu of units, rather than printing each one individually. I also use loops to make sure we get a valid FROM unit, a valid amount to convert, and a valid TO unit.

This code will run on all major operating systems. It's designed for Python3, but it's easy to modify for Python 2.

#!/usr/bin/env python3

''' Volumes conversion calculator 
    See http://stackoverflow.com/q/42743397/4014959

    Written by Ari Madian
    Modified by PM 2Ring 2017.03.12
'''

import os

# Clear the terminal. Works on Windows, Mac, and Linux
def clear(clear_cmd='cls' if os.name == 'nt' else 'clear'):
    os.system(clear_cmd)

# Various conversion ratios, in alphabetical order.
conversion_factors = {
    'cup': {'cup': 1, 'floz': 8.32674, 'gal': 0.0625, 'liter': 0.236588,
        'ml': 236.588, 'pint': 0.5, 'quart': 0.25, 'tbsp': 16, 'tsp': 48},
    'floz': {'cup': 0.125, 'floz': 1, 'gal': 0.0078125, 'liter': 0.0295735,
        'ml': 29.5735, 'pint': 0.0625, 'quart': 0.03125, 'tbsp': 2, 'tsp': 6},
    'gal': {'cup': 16, 'floz': 128, 'gal': 1, 'liter': 3.78541,
        'ml': 3785.41, 'pint': 8, 'quart': 4, 'tbsp': 256, 'tsp': 768},
    'liter': {'cup': 4.226757063, 'floz': 33.814, 'gal': 0.264172, 'liter': 1,
        'ml': 1000, 'pint': 2.11338, 'quart': 1.05669, 'tbsp': 67.628, 'tsp': 202.884},
    'ml': {'cup': 0.0042267571, 'floz': 0.033814, 'gal': 0.000264172, 'liter': 0.001,
        'ml': 1, 'pint': 0.00211338, 'quart': 0.00105669, 'tbsp': 0.067628, 'tsp': 0.202884},
    'pint': {'cup': 2, 'floz': 16, 'gal': 0.125, 'liter': 0.473176,
        'ml': 473.176, 'pint': 1, 'quart': 0.5, 'tbsp': 32, 'tsp': 96},
    'quart': {'cup': 4, 'floz': 32, 'gal': 0.25, 'liter': 0.946353,
        'ml': 946.353, 'pint': 2, 'quart': 1, 'tbsp': 64, 'tsp': 192},
    'tbsp': {'cup': 0.0625, 'floz': 0.5, 'gal': 0.00390625, 'liter': 0.0147868,
        'ml': 14.7868, 'pint': 0.03125, 'quart': 0.015625, 'tbsp': 1, 'tsp': 3},
    'tsp': {'cup': 0.0208333, 'floz': 0.1666666667, 'gal': 0.00130208323, 'liter': 0.00492892, 
        'ml': 4.92892, 'pint': 0.0104166667, 'quart': 0.0052083333, 'tbsp': 0.333333, 'tsp': 1},
}

# Valid menu selections are single digits
menu_numbers = '123456789'

#This is used to check if what the user entered is one of the nine acceptable units
acceptable_inputs = set(menu_numbers)

# Convert menu number to conversion ratio key
units = {
    '1': 'tbsp', '2': 'tsp', '3': 'cup', '4': 'quart', '5': 'floz',
    '6': 'gal', '7': 'ml', '8': 'liter', '9': 'pint',
}

# Short & long unit names, in menu order
unit_names = {
    'tbsp': ('Tbsp', 'Tablespoons'),
    'tsp': ('Tsp', 'Teaspoons'),
    'cup': ('C', 'Cups'),
    'quart': ('qt.', 'Quarts'),
    'floz': ('fl. oz.', 'Fluid Ounces'),
    'gal': ('gal.', 'Gallons'),
    'ml': ('ml', 'Milliliters'),
    'liter': ('L', 'Liters'),
    'pint': ('P', 'Pints'),
}

def get_unit():
    # Display the units menu
    for i in menu_numbers:
        key = units[i]
        short_name, long_name = unit_names[key]
        print('{0} {1} - {2}'.format(i, short_name, long_name))

    # Loop until we get an acceptable input
    while True:
        unit_num = input('Unit: ')
        if unit_num in acceptable_inputs:
            break
        print('Please select a unit by its number')
    return units[unit_num]

# Perform the conversion
def convert(from_key, amount, to_key):
    clear()
    from_name = unit_names[from_key][1]
    to_name = unit_names[to_key][1]
    print('Converting {0} to: {1}'.format(from_name, to_name))

    conv_factor = conversion_factors[from_key][to_key]
    calc = amount * conv_factor
    print(calc)

def main():
    print('Unit Converter\n\n')
    print('Select the unit you want to convert FROM\n')
    from_key = get_unit()

    # Get number to convert. Loop until we get a valid number.
    while True:
        try:
            amount = float(input('How many?: '))
            break
        except ValueError:
            print('Bad number. Please try again.')

    print('Select the unit you want to convert TO\n')
    to_key = get_unit()

    convert(from_key, amount, to_key)


if __name__ == '__main__':
    main()
PM 2Ring
  • 54,345
  • 6
  • 82
  • 182