tags:

views:

281

answers:

5

What is the upper bound of the range() function and how can I extend it, or alternately what's the best way to do this:

for i in range(1,600851475143):
+8  A: 

range(1, 600851475143) wants to generate a very large list in memory, and you'll get an out of memory error. To save memory, use xrange instead of range. Unfortunately, xrange doesn't work with large numbers (it's an implementation restriction) Example (raises OverflowError):

for i in xrange(1, 600851475143):
  print i

You can have large minimum or maximum values in your interval with range, if their difference is small. Example:

x = 1 << 200
print list(xrange(x, x + 3))

Output:

[1606938044258990275541962092341162602522202993782792835301376L, 1606938044258990275541962092341162602522202993782792835301377L, 1606938044258990275541962092341162602522202993782792835301378L]

A fancy solution to your original for loop problem:

def bigrange(a, b = None):
  if b is None:
    b = a
    a = 0
  while a < b:
    yield a
    a += 1

for i in bigrange(1, 600851475143):
  print i

A less fancy solution, which works even if you have continue in the loop body:

i = 1 - 1
while i < 600851475143 - 1:
  i += 1
  print i
pts
Do you know why you would use range() instead of xrange()? xrange() is faster and more memory-efficient.
jcoon
@coonj: this articles says that in some benchmarks range() was actually 1% faster. Also, xrange() has been removed in Python 3, I think.
Bastien Léonard
@coonj Sometimes you actually want a list of numbers rather than an iterator over those numbers. For example, deck = range(52); random.shuffle(deck); hand = deck[:5]On the other hand, using range when all you really want is an iterator over the numbers 1..n is really wasteful and that is where xrange comes in.
Aaron Maenpaa
@Bastien Actually range has been removed and xrange renamed range. If you really want a list you can just write deck = list(range(52)), but it encourages you to use the iterator unless you actually need the list.
Aaron Maenpaa
running the above example, I get an overflow error on Python 2.6.1
Josh Arenberg
Updated by answer how to avoid the OverflowError.
pts
+2  A: 

pts' answer led me to this in the xrange python docs:

Note

xrange() is intended to be simple and fast. Implementations may impose restrictions to achieve this. The C implementation of Python restricts all arguments to native C longs (“short” Python integers), and also requires that the number of elements fit in a native C long. If a larger range is needed, an alternate version can be crafted using the itertools module: islice(count(start, step), (stop-start+step-1)//step)

looks like it's a limitation of c python in particular.

Josh Arenberg
A: 

It depends on which version of Python you're using. I'm using 2.5.2 and xrange raises an OverflowError exception for large numbers. One solution is to write your own generator.

def g(start, stop):
    i = start
    while i < stop:
        yield i
        i += 1

x = 1<<200
for i in g(x, x+3):
    print i
tom10
+1  A: 

Have you considered just doing this? Or is there some reason you specifically need range()?

x = 1
while x < 600851475143:
    // some code
    x += 1
TM
A: 

Here's an answer using itertools. It's a little contrived, but it works:

from itertools import repeat, count, izip
for i,_ in izip(count(1), repeat(1, 600851475143)):
    ...

Another answer would be to write your own generator:

def my_xrange(a, b):
    while a < b:
        yield a
        a += 1

for i in my_xrange(1, 600851475143):
    ...
Rick Copeland