Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

for loop: range() result has too many items

59 views
Skip to first unread message

Peng Yu

unread,
Oct 13, 2009, 5:17:58 PM10/13/09
to pytho...@python.org
Hi,

The following code does not run because range() does not accept a big
number. Is there a way to make the code work. I'm wondering if there
is a way to write a for-loop in python similar to that of C style.

for(int i = 0; i < a_big_number; ++ i)

Regards,
Peng

$ cat for_loop.py
import sys

def foo():
for i in range(sys.maxint):
if i % 100 == 0:
print i

foo()
$ python for_loop.py
Traceback (most recent call last):
File "for_loop.py", line 8, in <module>
foo()
File "for_loop.py", line 4, in foo
for i in range(sys.maxint):
OverflowError: range() result has too many items

Mel

unread,
Oct 13, 2009, 5:29:10 PM10/13/09
to
Peng Yu wrote:

Are you using Python 2.x ??? If you are, range will accept your number, but
it will try to build a list holding sys.maxint integers, and you don't have
enough memory.

Try xrange instead.

Mel.


Steven D'Aprano

unread,
Oct 13, 2009, 5:39:46 PM10/13/09
to
On Tue, 13 Oct 2009 16:17:58 -0500, Peng Yu wrote:

> Hi,
>
> The following code does not run because range() does not accept a big
> number.

Incorrect.

>>> range(sys.maxint+2, sys.maxint+5)
[2147483649L, 2147483650L, 2147483651L]


> Is there a way to make the code work. I'm wondering if there is
> a way to write a for-loop in python similar to that of C style.
>
> for(int i = 0; i < a_big_number; ++ i)

An exact translation of that would be a while loop:

i = 0
while i < a_big_number:
i += 1


but that's not actually your problem. Your actual problem is that you're
trying to generate a list containing 2147483647 (sys.maxint) items. Each
item requires 8 bytes, so this will need a single contiguous block of at
least 16 gigabytes.

On my system, when I try it, I get MemoryError. You get OverflowError.

Try instead using a lazy list:

>>> xrange(sys.maxint)
xrange(2147483647)

> def foo():
> for i in range(sys.maxint):
> if i % 100 == 0:
> print i


Rather than iterating through every single integer between 0 and
2147483647, you can skip the ones you don't care about:

for i in xrange(0, sys.maxint, 100):
print i

This will run approximately 100 times faster than your code.

--
Steven

Andre Engels

unread,
Oct 13, 2009, 5:55:07 PM10/13/09
to Peng Yu, pytho...@python.org
On Tue, Oct 13, 2009 at 11:17 PM, Peng Yu <peng...@gmail.com> wrote:
> Hi,
>
> The following code does not run because range() does not accept a big
> number. Is there a way to make the code work. I'm wondering if there

> is a way to write a for-loop in python similar to that of C style.
>
> for(int i = 0; i < a_big_number; ++ i)
>
> Regards,
> Peng
>
> $ cat for_loop.py
> import sys
>
> def foo():
>  for i in range(sys.maxint):
>    if i % 100 == 0:
>      print i
>
> foo()
> $ python for_loop.py
> Traceback (most recent call last):
>  File "for_loop.py", line 8, in <module>
>    foo()
>  File "for_loop.py", line 4, in foo
>    for i in range(sys.maxint):
> OverflowError: range() result has too many items
> --
> http://mail.python.org/mailman/listinfo/python-list
>

Quite simple, use xrange (generates the numbers on the fly) rather
than range (creates the list, and gets the numbers from there):

for i in range(sys.maxint):
if i % 100 == 0:
print i

However, I think that the better Python way would be to use a generator:

def infinite_numbergenerator():
n = 0
while True:
yield n
n += 1

for i in infinite_numbergenerator():
...


--
André Engels, andre...@gmail.com

Andre Engels

unread,
Oct 13, 2009, 5:56:05 PM10/13/09
to Peng Yu, pytho...@python.org
On Tue, Oct 13, 2009 at 11:55 PM, Andre Engels <andre...@gmail.com> wrote:

> for i in range(sys.maxint):
>    if i % 100 == 0:
>       print i

Grmbl.... cut-and-paste error... I meant of course:

for i in xrange(sys.maxint):


if i % 100 == 0:
print i

--
André Engels, andre...@gmail.com

Rhodri James

unread,
Oct 13, 2009, 6:05:45 PM10/13/09
to Peng Yu, pytho...@python.org
On Tue, 13 Oct 2009 22:17:58 +0100, Peng Yu <peng...@gmail.com> wrote:

> The following code does not run because range() does not accept a big
> number. Is there a way to make the code work. I'm wondering if there
> is a way to write a for-loop in python similar to that of C style.

xrange()

Have you read the documentation at all?

--
Rhodri James *-* Wildebeest Herder to the Masses

Dave Angel

unread,
Oct 13, 2009, 6:49:08 PM10/13/09
to Andre Engels, pytho...@python.org
Andre Engels wrote:
> On Tue, Oct 13, 2009 at 11:55 PM, Andre Engels <andre...@gmail.com> wrote:
>
>
>> for i in range(sys.maxint):
>> if i % 100 =0:

>> print i
>>
>
> Grmbl.... cut-and-paste error... I meant of course:
>
> for i in xrange(sys.maxint):
> if i % 100 =0:
> print i
>
>

What version of Python gives an error on that code? My 2.6.2 works fine.

If you do need a larger xrange, you can easily write your own. Here's
one called brange(). It'd be a bit more work to make the 3-argument
version.

def brange(limit):
i = 0
while i < limit:
yield i
i += 1


Matt Nordhoff

unread,
Oct 13, 2009, 11:20:58 PM10/13/09
to Andre Engels, pytho...@python.org
Andre Engels wrote:
[snip]

> However, I think that the better Python way would be to use a generator:
>
> def infinite_numbergenerator():
> n = 0
> while True:
> yield n
> n += 1
>
> for i in infinite_numbergenerator():
> ...

That's what itertools.count() is for.

<http://docs.python.org/library/itertools.html#itertools.count>

It'll be faster, too, since it's written in C. Not that it really
matters, but it's always nice.
--

Matt Nordhoff

unread,
Oct 13, 2009, 11:32:39 PM10/13/09
to Andre Engels, pytho...@python.org

...Although itertools.count() is limited by sys.maxint (well,
PY_SSIZE_T_MAX), so I guess it isn't useful in this case.
--

Mark Dickinson

unread,
Oct 14, 2009, 4:54:44 AM10/14/09
to
On Oct 13, 10:39 pm, Steven D'Aprano

<ste...@REMOVE.THIS.cybersource.com.au> wrote:
> On Tue, 13 Oct 2009 16:17:58 -0500, Peng Yu wrote:
> > Hi,
>
> > The following code does not run because range() does not accept a big
> > number.
>
> Incorrect.
>
> >>> range(sys.maxint+2, sys.maxint+5)
>
> [2147483649L, 2147483650L, 2147483651L]

For what it's worth, there *is* a Python oddity lurking
under the surface here, at least for 64-bit. Here's
Python 2.6 on a 64-bit machine:

>>> range(2**31-1)


Traceback (most recent call last):

File "<stdin>", line 1, in <module>
MemoryError
>>> range(2**31)


Traceback (most recent call last):

File "<stdin>", line 1, in <module>


OverflowError: range() result has too many items

The first call tries to allocate a list containing
2**31-1 integers. At 32 bytes per entry (8 for the
list pointer, 24 for the integer itself), that's not
surprising on a machine with < 64 Gb of memory.

The second call, however, doesn't even try to
allocate the memory, but decides that the range can't
be represented. That's not right: this is an LP64
machine, so the size of the list can be represented,
and the start, stop and step values are representable
as C longs (which is what CPython uses internally for
this purpose). On a machine with >64 Gb of memory,
this call should succeed. On an LP64 machine with
<64 Gb of memory, it should produce MemoryError, not
OverflowError.

Mark

David C. Ullrich

unread,
Oct 15, 2009, 3:39:01 PM10/15/09
to
On Wed, 14 Oct 2009 01:54:44 -0700 (PDT), Mark Dickinson
<dick...@gmail.com> wrote:

>On Oct 13, 10:39�pm, Steven D'Aprano
><ste...@REMOVE.THIS.cybersource.com.au> wrote:
>> On Tue, 13 Oct 2009 16:17:58 -0500, Peng Yu wrote:
>> > Hi,
>>
>> > The following code does not run because range() does not accept a big
>> > number.
>>
>> Incorrect.
>>
>> >>> range(sys.maxint+2, sys.maxint+5)
>>
>> [2147483649L, 2147483650L, 2147483651L]
>
>For what it's worth, there *is* a Python oddity lurking
>under the surface here, at least for 64-bit. Here's
>Python 2.6 on a 64-bit machine:

Is that a 64-bit Python as well?

Mark Dickinson

unread,
Oct 15, 2009, 6:38:46 PM10/15/09
to
On Oct 15, 8:39 pm, David C. Ullrich <ullr...@math.okstate.edu> wrote:
> >For what it's worth, there *is* a Python oddity lurking
> >under the surface here, at least for 64-bit.  Here's
> >Python 2.6 on a 64-bit machine:
>
> Is that a 64-bit Python as well?

Yes.

Mark

Tim Roberts

unread,
Oct 16, 2009, 1:42:21 AM10/16/09
to
Matt Nordhoff <mnor...@mattnordhoff.com> wrote:
>
>That's what itertools.count() is for.
>
><http://docs.python.org/library/itertools.html#itertools.count>
>
>It'll be faster, too, since it's written in C. Not that it really
>matters, but it's always nice.

For being such a simple concept, I've been surprised how many places
itertools.count() has come in handy for me.
--
Tim Roberts, ti...@probo.com
Providenza & Boekelheide, Inc.

0 new messages