user2904154 - 1 year ago 171
Python Question

# NameError: name 'z' is not defined

I am trying to make a binary to decimal coverter for a project in my computing class and I get this error with my code: "NameError: name 'z' is not defined" I've looked up answers and they fix one error but give another. Here is the code:

``````bd = input("""
Would you like to convert a number into:
a) Binary to Decimal
b) Decimal to Binary
""")

if bd == 'a':
Please enter a Binary number. Up to, and including, 8 digits of 1 and 0
""")
z += 2
for i in range(8):
if answer [ i ] == '1':
``````

Any help would very much be appreciated!

Is this your first programming language? If so, let me introduce you to the concept of Variable Initialization.

When a computer is running code, it is processing bytes between the memory and the CPU. You probably know this already, but what you may not realize is that in your code, you are asking the computer to perform an operation on `z`, a variable that does not exist yet.

Keep something else in mind. Python does not need to initialize a variable in order to assign to it. So, why do you need to initialize `z` then before the program will run? The answer is simple: your first reference to `z` is an operation. Even though Python can automatically (without initialization) assign variables on the fly (different from other programming languages, usually), it still needs said variable to exist before math can be done with it.

The simple solution is to add `z = 0` at any point before `if bd == 'a':` (because if you put it after, every time it goes into the `if` statement, it will over-write `z` with `0`, ruining the logic for it.

Happy coding!

EDIT: In addition to this issue, the problem you will face with the error:

``````File "C:/Users/<USERNAME>/Desktop/Task 1.py", line 15, in <module> answer += 1*z**i TypeError: Can't convert 'int' object to str implicitly
``````

Comes from the line:

``````    if answer [ i ] == '1':
``````

You see, when you type `'1'`, you are saying that `1` is a string because you surround it with quotes, just the same as if you had written:

``````if answer [i] == "1":
``````

What you need, instead, is the line

``````if answer [i] == 1:
``````

Because that tells it to assign the number `1`. Then, in the operation

``````answer += 1*z**i
``````

You will be telling it to multiply three numbers instead of two numbers and the string "1".

In other languages like C, you must declare variables so that the computer knows the variable type. You would have to write `string variable_name = "string text"` in order to tell the computer that the variable is a string. In Python, the type casting happens automatically. Python sees `variable = "string text"` and it knows that because you used `""`, it is a string-type variable. Unfortunately, this means that you mistakenly made `1` a string.

Understand?

EDIT 2: The Happening

Okay, so you kept running into errors. And when I ran your code, I kept running into different errors. Because the of the tricky syntax and changing in types implicitly, I decided a much easier route to go was to rewrite the code and explain to you how and why it works. So, here is the new code:

``````bd = raw_input("""
Would you like to convert a number into:
a) Binary to Decimal
b) Decimal to Binary
""").lower()

## ORIGINAL CODE
##
##if bd == 'a':
##Please enter a Binary number. Up to, and including, 8 digits of 1 and/or 0
##""")
##
##    for i in range(8):
##        z += 2

##NEW CODE
if bd == 'a':
number_original = raw_input("Please enter a Binary number (a string of 1's and 0's)")

j = 0
number_converted = 0

for i in reversed(number):
if i == '1':
number_converted += 2**j
j+=1

print number_converted
``````

From top to bottom, I'll go over what I wrote (I'll skip over your code) and I'll explain what it does and how it does it. Hopefully, this will help you in the decimal->binary conversion, as I assume you still have that to do.

So we begin with a few changes to your opening question. Where before you had `bd=input("")`, you now have `bd=raw_input("").lower()`.

bd will still be `a` or `b`. But there was some shaky type handling in that statement, at least on my end. So, I made use of `raw_input()` which turns your answer into a string regardless of what it is. If you answer with `101010011` for instance, it will store the variable `"101010011"` and not the number `101010011` (though this would be wrong anyway-- it would be `base 10`, so it would actually be `101,010,011`)... I also added `.lower()`, which as you may guess, turns your answer from `whAtevErYouWritE` to `whateveryouwrite`. This is an example of data sanitation and is vital in a good program, because people can be stupid and expect a computer to know what they mean. Computers, of course, have no idea what you mean, so you have to be very careful, know what mistakes a user can make, and plan ahead for it (BONUS: Here's a comic on the subject, which you will now definitely get).

So onto the meat of the program. We start by testing the condition for answer `a` with:

``````if bd == 'a':
``````

Now, if you put in `A`, this would still work because of `.lower()`. If you put `b`, if wouldn't work (you have yet to put in your decimal->binary code!), and always remember that some day, someone will put in `C`, just to troll you, so include an `elif` for `b` and an `else` for anything else.

After this we encounter the first signs of it just being my code.

``````number_original = raw_input("Please enter a bin...
``````

I've named it number_original because in code, it's always best practice to be clear and concise. Remember, the variable name `this_is_the_variable_i_use_to_calculate_my_circumference` is better than `x` so long as it explains clearly what it is, and helps other people understand your work. More advanced coders like to be ambiguous in this case, but a lot of the time it's just showing off.

I used `raw_input()` again because I actually want my number to be stored as a string. Remember when I said that `101010011` would be `101,010,011` to the computer? This would be very difficult to check, because the computer will assume a base 10 number. Thus, I just had it stored as a string, `"101010011"`, and avoided that whole issue. There is also the added bonus to this that strings have manipulating methods that make it easier to work with, easier than the logic you were trying to introduce with `range(8)`. That manipulator can be seen shortly.

Next, we declare our variables:

``````j = 0 #This 'j' accomplishes the same work done by your 'z' variable.
number_converted = 0 #this will be correctly converted by the end, as we add to it.
``````

As mentioned in my original version of this post, these are initialized because the first time you operate on them inside the loop, you do math to them, and they need to exist as a number before you can do that. Even if they start at 0.

So now we look at the most interesting part, the `for` loop. Based on your original work, you kind of get how `for` loops work, but I'll go over them in a lot of detail so that hopefully, it helps you as much as possible when you need to see the big picture.

In a `for` loop, you are meant to iterate over a range of numbers. In your original code, you generated the range `[0,1,2,3,4,5,6,7]` to iterate over. I think you did this so you could keep track of which position in the binary number you were at, and I'm doing that as well, but in a different way, and one that I devised slowly in order to help you make the best decimal-to-binary system I could.

First, remember that `number` is a string now, so `"101010011". Next, realize that strings have indexes that can be accessed like so.

``````demo_string = "super mario brothers"
print demo_string[0]
print demo_string[1]
print demo_string[2]
print demo_string[3]
print demo_string[4:10]
print demo_string[:10] #if you leave out the first number, it starts at the beginning
print demo_string[10:] #if you leave out the last number, it ends at the end.
``````

The above code will give you the following result:

``````s
u
p
e
r mari
super mari
o brothers
``````

Take special notice that an index starts at 0, which is why `demo_string[1]` is `u` and not `s`.

Knowing this, you may begin to realize why we left `number_original` as a string: now we can use its index and iterate over that instead of making our own range with `range()`! This is why we can type `for i in reverse(number_original)`; because that makes it loop from `reverse(number_original)[0]` to `reverse(number_original)[i]`, as far as `i` is able to go. Note:We will go over why we are using `reverse()` shortly.

## It's time for number/computer science and math!

Have you learned yet about expressing every binary digit in the form of a power of two? I know you understand the concept underlying conversion in a binary number. Well, here's another cool trick you may or may not be aware of:

``````... #  #  #  #  #  # <--The binary number, eg "101010"
...32 16  8  4  2  1 <--What each digit stands for in decimal form
... 5  4  3  2  1  0 <--The power of two that it stands for (2^5=32, 2^4=16...)
``````

Another thing you'll realize is that typically (not always, but usually, binary numbers are read from right to left. This will come in handy in a moment).

So we're at the `for` loop. We know now that we can iterate through a string. But binary digits are read right-to-left. So, the binary number `10 = 2`, not `10 = 1`. This is why we wrote:

``````for i in reversed(string):
``````

Because now, the `for` loop will iterate backwards! It will read the string right-to-left for us.

We also know that `2^x = (digit value in decimal)`.

So what we'll do in each iteration of the `for` loop is:

• Check if `i == '1'` Note, this time we want it to be a string.
• If `i == '1'`, as in, the digit we're highlighting is a `'1'`, then...
• Take `number_converted` and add `number_converted + 2^j`
• Then accumulate once to `j`, so it's one higher for the next trip.

To put this visually, I'll do two loops on the number `101010011`.

Loop 4
j = 4
number_converted = 3 (still being converted)
is reversed(number_original)[3] == '1'? ( 1 1 0 0 1 0 1 0 1, so no)
then add 1 to j (j = 5)
Loop 5
j = 5
number_converted = 3 (still being converted)
is reversed(number_original)[4] == '1'? (1 1 0 0 1 0 1 0 1, so yes!)
then take number_converted (3) and add 2^j (2^5 = 16) to it (number_converted = 25) then add 1 to j (j = 6)
Loop 6
j = 6
number_converted = 35 (still being converted)
this will continue until end!

So there you have it. Binary to decimal, in python.