0

I'm trying to create a scientific calculator for an assignment. I'm looking for a bit of help with python syntax, and I think my design and pseudo code are doing well, but for whatever reason python isn't having any of my syntactical issues. Here is the code I have for converting binary to decimal.

I need the code to reprompt when the input is invalid, but when it does reprompt, it gets stuck in a loop of reprompting and won't give me any way out.

def bintodec(var):
    power = (len(var) + 1)
    value = ' '
    while True:

        var = input('Give a number to convert from binary to decimal: ')
        for x in range(len(var)):

            if (ord(var[x]) == 49):
                power -= 1
                value += x * (2 ** power)

            if (ord(var[x]) == 48):
                power -= 1
                value += x * (2 ** power)

            if power == -1:
                break

            else:
                boo = True

    return value

Any help is greatly appreciated!

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
Jay F.
  • 3
  • 1
  • The `break` statement only exits the innermost loop. See the duplicate (link above) for ways to refactor your code to break out of the outer loop. – Jim Stewart Nov 12 '18 at 01:08
  • 1
    Do you actually have to use `ord` here... The code would be much more readable if you just do `for x in var: if x == '0'`.... etc... Also you're doing the same operations for `0` and `1` so you might as well put those in the same block – Jon Clements Nov 12 '18 at 01:09
  • The answers to the question [Asking the user for input until they give a valid response](https://stackoverflow.com/questions/23294658/asking-the-user-for-input-until-they-give-a-valid-response) should help with getting input from the user. – martineau Nov 12 '18 at 02:32

1 Answers1

0

This is pretty classic. Reading in a base is easier than writing in one.

def bintodec(var):
    assert set(var) <= set("01") # Just check that we only have 0s and 1s
    assert isinstance(var, str) # Checks that var is a string

    result = 0
    for character in var: # character will be each character of var, from left to rigth
        digitvalue = ord(character) - ord("0")
        result *= 2
        result += digitvalue

    return result

Ok, how does it work ?

Well, it reads the value from left to right. digitvalue will contain 1 or 0. For each digit we read, if it is 0, there is nothing to add the result (so result += digitvalue adds indeed 0), but we still need take into account that there is one more 0 at the end of the number.

Now, in base 10, adding a zero to the end makes a number 10 times as big. This is the same in base 2. Adding a zero at the end makes a number twice as big. This is why we multiply it by 2.

Finally, if digitvalue is 1 instead of 0, we need to add 1 to the number and result += digitvalue does it.

Note: Just for things to be clear, the two for loops below are equivalent.

for character in var:
    pass # pass does nothing

for i in range(len(var)):
    character = var[i]
    pass

@JayF.:

Is there any way to reprompt without using assert?

I suppose you want to reprompt if the input is incorrect. You need to use a loop for that:

while True:
    var = input()
    if set(var) <= set("01"):
        print(bintodec(var))
        break # Remove this `break` statement if you want to reprompt forever
    else:
        # print("The input must consist of only 0s and 1s.")
        pass # `pass` does nothing.

If you leave the asserts in the bintodec function, it can be done in a more pythonic way, using exception handling:

while True:
    var = input()
    try:
        print(bintodec(var))
        break
    except AssertionError:
        print("The input must consist of only 0s and 1s.")
loxaxs
  • 2,149
  • 23
  • 27
Mathieu CAROFF
  • 1,230
  • 13
  • 19