3
def pi(times):
    seq = []
    counter = 0
    for x in range(times):
        counter += 2
        seq.append("((%f**2)/(%f*%f))*"%(float(counter), float(counter-1), float(counter+1)))
    seq.append("1.0")
    seq = "".join(seq)
    seq = eval(seq)
    return seq*2

Anywhere past 85000 terms I get a segmentation fault and python quits. How can I avoid this? Why is it crashing? Can't it just please use more memory or something?

ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
tekknolagi
  • 10,663
  • 24
  • 75
  • 119

2 Answers2

5

You appear to have found a bug in eval where it can't handle insanely long expressions:

>>> eval("1.0*"*10000+"1.0")
1.0
>>> eval("1.0*"*100000+"1.0")
# segfault here

I use the phrase "insanely long" advisedly though. Don't do it that way, calculate the pieces as you go. There is no reason to be using eval in this situation.

ncoghlan
  • 40,168
  • 10
  • 71
  • 80
  • wow thank you :) now I'm getting a syntaxerror when trying to return seq as an int, calculating on the fly – tekknolagi Mar 03 '11 at 07:05
  • i cannot believe i didn't calculate on the fly instead of using eval :O – tekknolagi Mar 03 '11 at 07:07
  • I've seen something about this before and it isn't really considered a bug so much as the programmer abusing eval. – Justin Peel Mar 03 '11 at 07:30
  • 5
    The segfault outcome is a bug. Simply declaring an expression that long to be unreasonable and refusing to accept it would be OK, but it should raise an exception in that case. – ncoghlan Mar 03 '11 at 07:58
  • Ah, it was a known defect, it just didn't have a tracker item. – ncoghlan Mar 03 '11 at 11:11
2

Why use eval() at all?

def pi(times):
    val = 1
    counter = 0
    for x in range(times) :
        counter += 2
        val *= float(counter)**2/(counter**2 - 1)
    return val * 2

Does the exact same thing.

NullUserException
  • 83,810
  • 28
  • 209
  • 234