1

I'm programming a calculator application using Python 3, and everything functions fine (I think), except when I attempt to use the my double_factorial() function. If I enter a number higher than 3, the program doesn't output anything and my computer overheats (I use a Macbook Pro, fully customized to be as powerful as possible). This is either a straight up computer issue, or a computer issue because of something wrong with my code. Is there anything wrong with my code that I might not be able to spot as a beginner? (note: I'm only posting the relevant sections):

def add(a,b):
    return(a + b)

def subtract(a,b):
    return(a - b)


def multiply(a,b):
    counter = 0
    for i in range(a):
        counter = add(counter, b)
    return(counter)

def divide(a,b):
    quotient = 0
    while a >= b:
        quotient = add(quotient, 1)
        a = subtract(a,b)
    return (quotient, a)

def factorial(a):
    c = 1
    while a > 1:
        c = multiply(c,a)
        a = subtract(a,1)
    return(c)

def double_factorial(a):
    og = factorial(a)
    return factorial(og)    

def equation():
    d = None    
    print("Valid operations: +, -, *, /, !, !!, =")
    c = eval(input("Integer: "))

    while d != "=":
        d = input("Operation: ")

        if d in ('+', '-', '*', '/', '!', '!!', '='):
            if d == "+":
                c = add(c, eval(input("Integer: ")))
            elif d == "-":
                c = subtract(c, eval(input("Integer: ")))
            elif d == "*":
                c = multiply(c, eval(input("Integer: "))) 
            elif d == "/":
                c = divide(c, eval(input("Integer: ")))
            elif d == "!":
                c = factorial(c)
            elif d == "!!":
                c = double_factorial(c)            
        elif d != "=":
            print("invalid")
    print(str(c))
Moca
  • 43
  • 1
  • 5
  • 1
    Please post function definitions of `multiply()` and `subtract()`. – andrew_reece Oct 15 '17 at 16:55
  • 2
    Note that double factorials scale rather rapidly, e.g. an input of `10` will require 3628800 `multiply()` calls for the second level of the calculation. – Amber Oct 15 '17 at 16:57
  • As an aside, you shouldn't use `eval(input(...))`. It's not really an issue with something like this, but generally, `eval` should be avoided, especially when taking input, because [it is dangerous](https://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html). You should just use `int` or `float`, since that is what you want anyway. – juanpa.arrivillaga Oct 15 '17 at 17:22
  • Everything has been updated! I just added all of the functions for convenience. Also, I'll keep the eval thing in mind when finalizing my code, that article was really helpful! – Moca Oct 15 '17 at 21:07

1 Answers1

1

4!! = 24! which is a huge number (as a rough estimation: 24! > 24 * 5^5 * 10^14, which means 4!! ~ 10^20 which is already close to sys.maxsize.

The next one, 5!! = 120! which is immensely larger. (120! >> 10^90 * 100^20 ~ 10^130).

If you provide the code for your multiply function, it might help to detect what exactly is going on (in theory, Python3 can calculate e.g. 10^100 successfully), but I suspect your computer has reached its limits here.

Update: now that you have provided your code, there is at least one more potential issue: in your multiply method, you use range(a), which actually instantiates the requested sequence in memory. Assuming 4 bytes per int, this results in at least a*4 bytes needed. E.g. if your machine had e.g. 1TB free memory (which it probably doesn't have) this already would limit the value of a: a < 10^12/4.

Also, your "a" is the larger of the multiplied values, so changing the order of the operands sent to multiply would help as well, because then the range will be smaller (corresponding to n! instead of partially computed n!!)

You can mitigate this somewhat by using xrange instead, which is a sequence iterator.

Ashalynd
  • 11,728
  • 2
  • 29
  • 35
  • Indeed. My server calculated `8!!` in 0.8s but needed 85s for `9!!`. Exponential growth is already peanuts compared to `n!`. So you can forget about `n!!`. – Eric Duminil Oct 15 '17 at 18:16
  • I edited my initial post with all of the functions in the program including multiply! This is a learning exercise for looping structures, which is why I'm calling my add() function instead of just multiplying. – Moca Oct 15 '17 at 21:10
  • 1
    In python 3 there is no `xrange`, only `range`, but my code worked after I switch the order of the operands sent to multiply, so thank you! – Moca Oct 16 '17 at 01:32
  • Correct: https://stackoverflow.com/questions/15014310/why-is-there-no-xrange-function-in-python3 (I use Python2 way more often than pure Python3 ) – Ashalynd Oct 16 '17 at 16:01