Python Forum
Simple conditional not working as expected - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Simple conditional not working as expected (/thread-40612.html)



Simple conditional not working as expected - return2sender - Aug-26-2023

Python beginner here--

I wrote a practice program that converts decimal numbers to binary and vice versa. It works great! For example:

>>> Enter 0 to convert decimal (denary) to binary,
    or enter 1 to convert binary to decimal: 1

Enter a number in binary to convert to decimal (denary): 1000101

The number 1000101 expressed in decimal (denary) is: 69

Would you like to perform another conversion? (y/n): y

>>> Enter 0 to convert decimal (denary) to binary,
    or enter 1 to convert binary to decimal: 0

Enter a number in decimal (denary) to convert to binary: 69

The number 69 expressed in binary is: 1000101 
However, I noticed that I hadn't entered a condition if the user enters a non-binary number when binary is requested. This returns a ridiculous response as follows:

>>> Enter 0 to convert decimal (denary) to binary,
    or enter 1 to convert binary to decimal: 1

Enter a number in binary to convert to decimal (denary): 69

The number 69 expressed in decimal (denary) is: 21 
So I attempted to write a simple conditional to exclude this possibility and simply re-request the input if non-binary numbers are entered, as follows. I also tried iterating over the whole string (for z in range(len(binNum)), etc).

def binToDec():
    binNum = input("Enter a number in binary to convert to decimal (denary): ")
    for z in binNum:
        if z != (0 or 1):
            print("Please enter a valid binary number")
            return binToDec()
    denNum = 0
    for i in range(len(binNum)):
        denNum += (int(binNum[-1*(i+1)])*(2**i))
    print()
    print(f"The number {binNum} expressed in decimal (denary) is: {denNum}")
    return True

binToDec() 
In every case that I tried, binary digits trigger the return clause the same as non-binary digits. I can't figure out why this is happening. It seems like a very simple and straightforward problem, yet it is eluding me.

Thank you in advance for any help!


RE: Simple conditional not working as expected - Gribouillis - Aug-26-2023

There are at least two problems
  • The value of the expression 0 or 1 in Python is 1, so you are actually testing if z != 1. If you want to test whether an expression has a value different from 0 and 1, you could write if z not in (0, 1)
  • In our case, however it won't work because z is not an integer, it a string such as '0' or '1' these strings are never equal to the integers 0 or 1. So, you could write if z not in ('0', '1') instead.
Your problem is a part of a more general problem called Data Validation. Every time a user enters data into a program, some sort of data validation must be performed to ensure that there is no error.


RE: Simple conditional not working as expected - return2sender - Aug-26-2023

Ah, makes sense. Thank you so much! By the way I had tried converting the string to int and also ('0' or '1') but obviously that didn't get to the root of the problem which was using the boolean operator.

Much appreciated!


RE: Simple conditional not working as expected - deanhystad - Aug-26-2023

This should not be a recursive function. Use recursion when the value of the function is defined using the function, such as the Fibbonacci sequence:

fibbo(n) = fibbo(n-1) + fibbo(n-2)

You are using recursion to make a loop.

I would write your function like this:
def enter_binary_number():
    while True:
        binary = input("Enter a binary number: ")
        value = 0
        for digit in binary:
            if digit not in "01":
                print(f"'{binary}' not a a valid binary number")
                break
            value = value * 2 + (1 if digit == '1' else 0)
        else:
            return value
 
print(enter_binary_number())
Instead of recursion, this function uses a while loop.


RE: Simple conditional not working as expected - Gribouillis - Aug-27-2023

(Aug-26-2023, 10:28 PM)deanhystad Wrote: Use recursion when the value of the function is defined using the function, such as the Fibbonacci sequence
Note that blind use of recursion to compute the Fibbonacci sequence is the worst thing you can do in terms of efficiency. A while loop is much better there too.


RE: Simple conditional not working as expected - return2sender - Aug-27-2023

(Aug-26-2023, 10:28 PM)deanhystad Wrote: This should not be a recursive function. Use recursion when the value of the function is defined using the function, such as the Fibbonacci sequence:

[...]

Instead of recursion, this function uses a while loop.

Thanks for the suggestion! Is there a functional reason for preferring a while loop as opposed to recursion? I have frequently been using recursion to loop because it seems like an efficient and convenient strategy.

Also I'm a little confused by the placement and indentation of the value and else clauses. I see that the code works but I don't follow the syntax.


RE: Simple conditional not working as expected - Gribouillis - Aug-27-2023

(Aug-27-2023, 12:52 PM)return2sender Wrote: I see that the code works but I don't follow the syntax.
It is the for ... else ... syntax. The else part is executed when the for loop is finished unless the loop exited with a break or return statement.


RE: Simple conditional not working as expected - deanhystad - Aug-27-2023

Recursion is resource intensive. Each function call context must be stored, just like with a regular function call, but while regular code often maxes out at a depth of 3 or 4 (a calls b, b calls c, c calls d, d calls e), recursion can quickly go much deeper. Recursion can quickly gobble up all the memory and cause the program to crash. That is why Python places a limit on how many levels deep a function call can go.

The "else" is paired with the "for", not the "if". In a for...else statement the else part is executed on completion of the for loop. If the for loop ends because of a break statement, the else part is not executed. In my example I only want to return a value if all the binary digits were processed. If an invalid input is encountered, I want to print the message and get a new input.


RE: Simple conditional not working as expected - return2sender - Aug-27-2023

Makes sense now. I was, of course, assuming that the Else was associated with the If statement which naturally led to the confusion.