1

A problem with nested while loop and nested if/elif. English isn't my first language, sorry. I'll show the code after description so you could understand what I'm talking about.

I've started to study Python a few weeks ago. Today I've faced the issue with while loop and if/elif. I don't understand why it's not working the way I expected. I'm trying to make the program collect user's numbers input into 4 lists depending on the option they chose: sum, subtract, multiply and divide. I want the program to calculate choosen option with the list of numbers user did input. It seems to be working, but there is an unresolved question. I'm trying to make the program working in case of invalid input inside each nested while loops - no luck. The thing I call the invalid input is something other than a number or a keyword (sum, subtract, multiply, divide, quit.

import math


while True:
    # Предложение выбрать нужную операцию.
    option = input("\nВыберите программу: "
                   "\n1) Сложение "
                   "\n2) Вычитание "
                   "\n3) Умножение "
                   "\n4) Деление"
                   "\nВведите quit для выхода."
                   "\n> ")
    option = option.lower()

    # Переменные для вмещения вводимых чисел.
    sum_list = []  # список для операции сложения
    subtract_list = []  # список для операции вычитания
    multiply_list = []  # список для операции умножения
    divide_list = []  # список для операции деления

    if option in ["1", "1)", "сложение"]:
        print("Введите числа по одному, затем — «sum» для сложения.")
        while True:
            num = input("> ")
            if num == "sum":
                break
            sum_list.append(float(num))
        # Ввод операции сложения.
        sum_result = sum(sum_list)
        print(f"Результат операции сложения: {sum_result}")

    elif option in ["2", "2)", "вычитание"]:
        print("Введите числа по одному, затем — «subtract» для вычитания.")
        while True:
            num = input("> ")
            if num == "subtract":
                break
            subtract_list.append(float(num))
        # Ввод операции вычитания.
        subtract_result = subtract_list[0] - sum(subtract_list[1:])
        print(f"Результат операции вычитания: {subtract_result}")

    elif option in ["3", "3)", "умножение"]:
        print("Введите числа по одному, затем — «multiply» для умножения.")
        while True:
            num = input("> ")
            if num == "multiply":
                break
            multiply_list.append(float(num))
        # Ввод операции умножения.
        multiply_result = math.prod(multiply_list)
        print(f"Результат операции умножения: {multiply_result}")

    elif option in ["4", "4)", "деление"]:
        print("Введите числа по одному, затем — «divide» для деления.")
        while True:
            num = input("> ")
            if num == "divide":
                break
            divide_list.append(float(num))
        # Ввод операции деления.
        divide_result = divide_list[0] / math.prod(divide_list[1:])
        print(f"Результат операции деления: {divide_result}")
    # Для выхода.
    elif option == "quit":
        print("Выход из программы...\n...завершён.")
        exit()
    # Неправильный ввод на этапе выбора программы.
    else:
        print("Вы не выбрали программу. Попробуйте заново.")
        option = input("> ").lower()
        continue

I've tried different things, I've spent the whole day - I just don't know how to make the program run further in case of invalid input inside each nested while loops. This is what I'm calling nested while loop:

    if option in ["1", "1)", "сложение"]:
        print("Введите числа по одному, затем — «sum» для сложения.")
        while True:
            num = input("> ")
            if num == "sum":
                break
            sum_list.append(float(num))
        # Ввод операции сложения.
        sum_result = sum(sum_list)
        print(f"Результат операции сложения: {sum_result}")

If I choose any option (sum, etc) and then enter some word instead of a number a keyword (sum, etc), I'll get this error:

Traceback (most recent call last):
  File "myfile.py", line 27, in <module>
    sum_list.append(float(num))
ValueError: could not convert string to float: 'this is the error if I enter something other than a number or a keyword (sum, subtract, multiply, divide, quit)'
3
  • 2
    Have you tried using try: sum_list.append(float(num)); except ValueError: print("Please provide a number")? Commented May 22, 2023 at 20:00
  • If you want to abort the current iteration of a loop and go straight to the next iteration of the same loop, you can use continue (docs.python.org/3/tutorial/…). So if you find invalid input, maybe you want to print a message to the user, then continue. Commented May 22, 2023 at 20:01
  • 1
    @BRemmelzwaal, yes, I've tried, but I probably put "try" somewhere else above and it didn't work. Now I tried again and it worked. Thank you! Commented May 22, 2023 at 20:37

1 Answer 1

1

If you try to cast something to a float which can't be casted to a float, you will get an error and your program will end.

There's generally two ways to deal with errors, check if it's valid first ("ask permission"), or try to do the thing and, if there's an error, deal with the error instead of letting the program die ("ask forgiveness"). In Python we usually use the "ask forgiveness" approach. Here's how that would look:

while True:
    num = input("> ")
    if num == "sum":
        break
    try:
        parsed_number = float(num)
        sum_list.append(parsed_number)
    except ValueError:
        print("I'm sorry but the input needs to be a number. Try again.")

Asking "permission" would be more difficult in this case but you could try:

permitted_float_chars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "."]
while True:
    num = input("> ")
    if num == "sum":
        break
    if all((character in permitted_float_chars for character in num)):
        parsed_number = float(num)
        sum_list.append(parsed_number)
    else:
        print("I'm sorry but the input needs to be a number. Try again.")

I'm sure there's a library for this but since you're learning I'll rather not look.

Update: Based on comment from tdelaney below. Better is:

import re
# the regular expression requires 1 or more numbers between 0 and 9
# followed by a period,
# followed by zero or more numbers
# Or, other way around, 0 or more numbers, period, 1 or more numbers
# Or, just numbers, at least one
FLOAT_REGEX = re.compile("^(([0-9]+\.[0-9]*)|([0-9]*\.[0-9]+)|([0-9]+))$")

while True:
    num = input("> ")
    if num == "sum":
        break
    if FLOAT_REGEX.search(num) is not None:
        parsed_number = float(num)
        sum_list.append(parsed_number)
    else:
        print("I'm sorry but the input needs to be a number. Try again.")
Sign up to request clarification or add additional context in comments.

2 Comments

And you don't really need the intermediate parsed_number. sum_list.append(float(num)) would do. The ask permissions code could use some refinement. Something like ".111...33..." would pass the test. I think a regular expression would be good.
Thanks @tdelaney. Updated. (I'm keeping the intermediate tho ;) Just feel that, for beginners especially, easier to debug when you get the line number in an error if there's only one thing per line).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.