3

To practice and better understand the for loop, I have designed a function that computes the factorial of a given number. I get pretty much everything beside the role of the iterator (loop variable).

Here is the function I designed:

def main():
    print("This program computes the factorial of a number!")
    n = eval(input("Enter a whole number: "))
    fact = 1
    for factor in range(n, 1, -1):
        fact = fact * factor
    print("The factorial of {} is {}!".format(n, fact))
main()

When I run the program for the factorial of 6, the function prints: The factorial of6is 720!

I'm looking to understand what role and relationship the input n given by the program user has on the iterator (loop variable) factor?

To test this out, I removed the iterator (loop variable) factor and replaced it with the input variable n.

def main():
    print("This program computes the factorial of a number!")
    n = eval(input("Enter a whole number: "))
    fact = 1
    for n in range(n, 1, -1):
        fact = fact * n
    print("The factorial of {} is {}!".format(n, fact))
main()

When I run the program for the same factorial of 6 that I used with the previous piece of code, the function prints: The factorial of2is 720!

Why do I get two different answers when I ask Python to compute the same factorial number. Clearly, there is something not right with the latter piece of code, which I assume has something to do with the relationship between the input variable n and the iterator (loop variable) factor.

5
  • 1
    You're overwriting the original variable n by using it as a loop variable in the second version.
    – bereal
    Commented Feb 19, 2015 at 15:24
  • 1. There's a math.factorial function; 2. n is being overwritten by the for loop.
    – Mark R.
    Commented Feb 19, 2015 at 15:25
  • 1
    Unrelated to the question, but important: for Guido's sake, don't use eval. int(input(...)) is enough.
    – bereal
    Commented Feb 19, 2015 at 15:28
  • @bereal: Indeed. There's a reason the old 2.x input() was scrapped.
    – Kevin
    Commented Feb 19, 2015 at 15:31
  • Thanks bereal, Mark and Kevin for the clarifications. Makes sense. Heard about the potential consequences of using eval. Thanks for the reminder.
    – user4581398
    Commented Feb 19, 2015 at 15:36

4 Answers 4

3

Start with your working code:

def main():
    print("This program computes the factorial of a number!")
    n = eval(input("Enter a whole number: "))
    fact = 1
    for factor in range(n, 1, -1):
        fact = fact * factor
    print("The factorial of {} is {}!".format(n, fact))
main()

Add a print (protip: this is a highly useful debugging trick):

def main():
    print("This program computes the factorial of a number!")
    n = eval(input("Enter a whole number: "))
    fact = 1
    for factor in range(n, 1, -1):
        print(factor)  # Add this line
        fact = fact * factor
    print("The factorial of {} is {}!".format(n, fact))
main()

You should see output like this:

6
5
4
3
2
The factorial of 6 is 720!

As you can see, the factor variable changes each time through the loop. It takes on each successive value in the range() you specified.

When you change the loop variable to n, it's getting overwritten with these values.

6
  • So the iterator (loop variable) sort of protect the original value of variable "n", is that correct?
    – user4581398
    Commented Feb 19, 2015 at 15:35
  • The value doesn't need "protection" as such. You just need to be careful not to overwrite it. Think of the loop as running factor = 6... factor = 5, ... etc. all the way down to 2. If you use n instead of factor, the old value of n will be gone.
    – Kevin
    Commented Feb 19, 2015 at 15:40
  • Makes perfect sense. Appreciate the help Kevin. All the best!
    – user4581398
    Commented Feb 19, 2015 at 15:41
  • Also see my answer. I will reiterate it here though. You are going from n to 2 with the current range range(n, 1, -1) by changing this to range(1, n+1, 1) it will allow you to go from 1 to 6 and get the correct output of The factorial of 6 is 720.
    – RPBruiser
    Commented Feb 19, 2015 at 15:44
  • @RPBruiser: Multiplying the values from n to 2 will give the same answer as multiplying from 1 to n. Multiplication is commutative and multiplication by 1 changes nothing. OP's first example already produces correct output.
    – Kevin
    Commented Feb 19, 2015 at 15:46
0

In your second program, by the time the function has run up to the print statement, n has been changed by the for loop. So whilst n is changing as you expect it to within the loop, by the time you come to print n it has been overwritten by the loop.

0
0
  1. Overwrite variable:

As user enter value is define in n variable. and in second example n is again define in for loop. so variable n is overwrite. Check the is of n variable.

e.g.

>>> n = 6
>>> id(n)
160708724
>>> n = 2
>>> id(n)
160708772
>>> 
  1. Use exception handle during type casting when code is excepting value from the Keyboard.

e.g. Code want to number from the keyboard.

>>> try:
...    n = int(raw_input("Enter number:"))
... except ValueError:
...    print "Enter only number value."
... 
Enter number:99
>>> n
99
>>> type(n)
<type 'int'>
>>> try:
...    n = int(raw_input("Enter number:"))
... except ValueError:
...    print "Enter only number value."
... 
Enter number:test
Enter only number value.
>>> 
  1. Related to your second example: I just print the value of n

code:

def factorialGenerator():
    print("This program computes the factorial of a number!")
    while True:
        try:
            n = int(raw_input("Enter a whole number: "))
            break
        except ValueError:
            print "Enter only digit."

    print "\nUser enter value %d and its id %s\n"%(n, id(n))

    fact = 1
    for n in range(n, 1, -1):
        print "In for loop value %d and its id %s"%(n, id(n))
        fact = fact * n

    print("\nThe factorial of {} is {}!".format(n, fact))


if __name__=="__main__":
    factorialGenerator()

output:

This program computes the factorial of a number!
Enter a whole number: r
Enter only digit.
Enter a whole number: 6

User enter value 6 and its id 142415988

In for loop value 6 and its id 142415988
In for loop value 5 and its id 142416000
In for loop value 4 and its id 142416012
In for loop value 3 and its id 142416024
In for loop value 2 and its id 142416036

The factorial of 2 is 720!
0

Try:

def main():
    print("This program computes the factorial of a number!")
    n = eval(input("Enter a whole number: "))
    fact = 1
    for n in range(1, n+1, 1):
        fact = fact * n
    print("The factorial of {} is {}!".format(n, fact))
main()

Your problem is that your are overwriting n at 6 to be 2, where with the new range you are overwriting it to begin with until you are at the desired n value.