niXforums Forum Index
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   PreferencesPreferences   Log in to check your private messagesLog in to check your private messages   Log inLog in 
·  nixdoc.net ·  man pages ·  Linux HOWTOs ·  FreeBSD Tips ·  Forums
navigation Forum index » Programming » python
range() is not the best way to check range?
Post new topic   Reply to topic Page 1 of 3 [43 Posts] View previous topic :: View next topic
Goto page:  1, 2, 3 Next
Author Message
Dan Bishop
*nix forums addict


Joined: 24 Feb 2005
Posts: 91

PostPosted: Tue Jul 18, 2006 2:49 am    Post subject: Re: range() is not the best way to check range? Reply with quote

Summercoolness@gmail.com wrote:
Quote:
it seems that range() can be really slow:
....
if i in range (0, 10000):

This creates a 10,000-element list and sequentially searches it. Of
course that's gonna be slow.
Back to top
Leif K-Brooks
*nix forums Guru Wannabe


Joined: 22 Feb 2005
Posts: 132

PostPosted: Tue Jul 18, 2006 2:59 am    Post subject: Re: range() is not the best way to check range? Reply with quote

Summercoolness@gmail.com wrote:
Quote:
or is there an alternative use of range() or something similar that can
be as fast?

You could use xrange:

leif@ubuntu:~$ python -m timeit -n10000 "1 in range(10000)"
10000 loops, best of 3: 260 usec per loop
leif@ubuntu:~$ python -m timeit -n10000 "1 in xrange(10000)"
10000 loops, best of 3: 0.664 usec per loop
Back to top
Dan Bishop
*nix forums addict


Joined: 24 Feb 2005
Posts: 91

PostPosted: Tue Jul 18, 2006 3:09 am    Post subject: Re: range() is not the best way to check range? Reply with quote

Leif K-Brooks wrote:
Quote:
Summercoolness@gmail.com wrote:
or is there an alternative use of range() or something similar that can
be as fast?

You could use xrange:

leif@ubuntu:~$ python -m timeit -n10000 "1 in range(10000)"
10000 loops, best of 3: 260 usec per loop
leif@ubuntu:~$ python -m timeit -n10000 "1 in xrange(10000)"
10000 loops, best of 3: 0.664 usec per loop

That's only because you're choosing a number that's early in the list.

~$ python -m timeit -n10000 "1 in xrange(10000)"
10000 loops, best of 3: 1.22 usec per loop
~$ python -m timeit -n10000 "9999 in xrange(10000)"
10000 loops, best of 3: 1.24 msec per loop

That's *milliseconds*, not microseconds.
Back to top
John Machin
*nix forums Guru


Joined: 19 Feb 2005
Posts: 608

PostPosted: Tue Jul 18, 2006 3:09 am    Post subject: Re: range() is not the best way to check range? Reply with quote

On 18/07/2006 12:41 PM, Summercoolness@gmail.com wrote:
Quote:
it seems that range() can be really slow:

the following program will run, and the last line shows how long it ran
for:

import time

startTime = time.time()

a = 1.0
for i in range(0, 30000):
if i in range (0, 10000):
a += 1
if not i % 1000: print i

print a, " ", round(time.time() - startTime, 1), "seconds"


---------------------------------
the last line of output is
---------------------------------

10001.0 22.8 seconds

so if i change the line

if i in range (0, 10000):

to

if i >= 0 and i < 10000:

the the last line is

10001.0 0.2 seconds

so approximately, the program ran 100 times faster!

or is there an alternative use of range() or something similar that can
be as fast?

Some things to try:
1a. Read what the manual has to say about the range() function ... what
does it produce?

1b. Read what the manual has to say about time.time() and time.clock().
Change over to using time.clock(). Change the round(...., 1) to (say) 4.

Alternatively, use something like this:

print "%.1f ... %.4f seconds" % (a, time.clock() - startTime)

1c. Repeat the two ways that you tried already.

2. First alternative:

Do this:

test_range = range(10000)

*once*, just after "a = 1.0".

and change your if test to

if i in test_range:

3. Now change that to:

test_range = set(range(10000))

4. Now forget about test_range, and change your if test to this:

if 0 <= i < 10000:

HTH,
John
Back to top
Sreeram Kandallu
*nix forums addict


Joined: 02 Jun 2006
Posts: 58

PostPosted: Tue Jul 18, 2006 3:24 am    Post subject: Re: range() is not the best way to check range? Reply with quote

Summercoolness@gmail.com wrote:
Quote:
so if i change the line
if i in range (0, 10000):
to
if i >= 0 and i < 10000:
[snip;]
is there an alternative use of range() or something similar that can
be as fast?


you've found that alternative yourself! just use the comparison operators...

in fact, you can write a little more compact as:
if 0 <= i < 10000 :


[sreeram;]
Back to top
Grant Edwards
*nix forums Guru


Joined: 21 Feb 2005
Posts: 1227

PostPosted: Tue Jul 18, 2006 4:13 am    Post subject: Re: range() is not the best way to check range? Reply with quote

On 2006-07-18, Summercoolness@gmail.com <Summercoolness@gmail.com> wrote:

Quote:
it seems that range() can be really slow:

the following program will run, and the last line shows how long it ran
for:

import time

startTime = time.time()

a = 1.0
for i in range(0, 30000):
if i in range (0, 10000):
a += 1
if not i % 1000: print i

print a, " ", round(time.time() - startTime, 1), "seconds"


Quote:
or is there an alternative use of range() or something similar that can
be as fast?

Creating and then searching a 10,000 element list to see if a
number is between two other numbers is insane.

Using xrange as somebody else suggested is also insane.

If you want to know if a number is between two other numders,
for pete's sake use the comparison operator like god intended.

if 0 <= i <= 10000:

--
Grant Edwards grante Yow! ANN JILLIAN'S HAIR
at makes LONI ANDERSON'S
visi.com HAIR look like RICARDO
MONTALBAN'S HAIR!
Back to top
tactics40@gmail.com
*nix forums beginner


Joined: 13 Jun 2006
Posts: 33

PostPosted: Tue Jul 18, 2006 4:56 am    Post subject: Re: range() is not the best way to check range? Reply with quote

Grant Edwards wrote:
Quote:
for pete's sake use the comparison operator like god intended.

if 0 <= i <= 10000:

I'm assuming you used Python's compound comparison as opposed to the
C-style of and'ing two comparisons together to emphasize the fact it is
god's chosen way of doing this Wink
Back to top
Marc 'BlackJack' Rintsch
*nix forums Guru Wannabe


Joined: 03 Mar 2005
Posts: 146

PostPosted: Tue Jul 18, 2006 7:27 am    Post subject: Re: range() is not the best way to check range? Reply with quote

In <1153198570.592653.203310@h48g2000cwc.googlegroups.com>, tac-tics
wrote:

Quote:
Grant Edwards wrote:
for pete's sake use the comparison operator like god intended.

if 0 <= i <= 10000:

I'm assuming you used Python's compound comparison as opposed to the
C-style of and'ing two comparisons together to emphasize the fact it is
god's chosen way of doing this Wink

Pete doesn't like to be called god in public. ;-)

Ciao,
Marc 'BlackJack' Rintsch
Back to top
Nick Craig-Wood
*nix forums Guru Wannabe


Joined: 23 Feb 2005
Posts: 104

PostPosted: Tue Jul 18, 2006 8:30 am    Post subject: Re: range() is not the best way to check range? Reply with quote

Grant Edwards <grante@visi.com> wrote:
Quote:
Creating and then searching a 10,000 element list to see if a
number is between two other numbers is insane.

Using xrange as somebody else suggested is also insane.

Aye to both

Quote:
If you want to know if a number is between two other numders,
for pete's sake use the comparison operator like god intended.

if 0 <= i <= 10000:

Sets are pretty fast too, and have the advantage of flexibility in
that you can put any numbers in you like

$ python2.4 -m timeit -s 's=range(0,10000); i=5000' 'i in s'
1000 loops, best of 3: 228 usec per loop

$ python2.4 -m timeit -s 's=set(range(0,10000)); i=5000' 'i in s'
1000000 loops, best of 3: 0.312 usec per loop

$ python2.4 -m timeit -s 'i=5000' '0 <= i < 10000'
1000000 loops, best of 3: 0.289 usec per loop

The below prints

range) That took 21.512 seconds: result 10001.0
set) That took 0.023 seconds: result 10001.0
comparison) That took 0.024 seconds: result 10001.0

.............................................................

import time

start = time.time()
a = 1.0
for i in range(0, 30000):
if i in range(0, 10000):
a += 1
dt = time.time() - start
print "range) That took %.3f seconds: result %s" % (dt, a)

start = time.time()
a = 1.0
mine = set(range(0, 10000))
for i in range(0, 30000):
if i in mine:
a += 1
dt = time.time() - start
print "set) That took %.3f seconds: result %s" % (dt, a)

start = time.time()
a = 1.0
mine = set(range(0, 10000))
for i in range(0, 30000):
if 0 <= i < 10000:
a += 1
dt = time.time() - start
print "comparison) That took %.3f seconds: result %s" % (dt, a)

--
Nick Craig-Wood <nick@craig-wood.com> -- http://www.craig-wood.com/nick
Back to top
Paul Boddie
*nix forums Guru Wannabe


Joined: 20 Feb 2005
Posts: 222

PostPosted: Tue Jul 18, 2006 9:22 am    Post subject: Re: range() is not the best way to check range? Reply with quote

John Machin wrote:
Quote:
On 18/07/2006 12:41 PM, Summercoolness@gmail.com wrote:
it seems that range() can be really slow:

[...]

Quote:
Some things to try:
1a. Read what the manual has to say about the range() function ... what
does it produce?

Indeed. Still, the addition of a __contains__ method to range (and
xrange) would permit acceptable performance for the code given. Perhaps
this is a convenience worth considering for future Python releases.

Paul
Back to top
Andy Dingley
*nix forums beginner


Joined: 19 Mar 2006
Posts: 11

PostPosted: Tue Jul 18, 2006 10:54 am    Post subject: Re: range() is not the best way to check range? Reply with quote

Summercoolness@gmail.com wrote:

Quote:
it seems that range() can be really slow:

if i in range (0, 10000):

RTFM on range()

You're completely mis-using it here, using it with an if ... in ...
test. The purpose of range() in Python is as loop control, not
comparisons! It's not a SQL BETWEEN statement.

Although you _can_ do this (you've done it!) you've also found that
it's slow. Many people would argue that even using range() for loop
control is unusably slow.
Back to top
Leif K-Brooks
*nix forums Guru Wannabe


Joined: 22 Feb 2005
Posts: 132

PostPosted: Tue Jul 18, 2006 11:09 am    Post subject: Re: range() is not the best way to check range? Reply with quote

Grant Edwards wrote:
Quote:
Using xrange as somebody else suggested is also insane.

Sorry about that, I somehow got the misguided notion that xrange defines
its own __contains__, so that it would be about the same speed as using
comparison operators directly. I figured the OP might have a better
reason for wanting to use range() than his post mentioned -- perhaps the
range to check was being passed from a function, and it would be easier
to pass an object than a tuple of lower and upper bound -- but since
xrange does looping for a membership test, my suggestion was indeed insane.
Back to top
John Machin
*nix forums Guru


Joined: 19 Feb 2005
Posts: 608

PostPosted: Tue Jul 18, 2006 11:55 am    Post subject: Re: range() is not the best way to check range? Reply with quote

On 18/07/2006 7:22 PM, Paul Boddie wrote:
Quote:
John Machin wrote:
On 18/07/2006 12:41 PM, Summercoolness@gmail.com wrote:
it seems that range() can be really slow:

[...]

Some things to try:
1a. Read what the manual has to say about the range() function ... what
does it produce?

Indeed. Still, the addition of a __contains__ method to range (and
xrange) would permit acceptable performance for the code given. Perhaps
this is a convenience worth considering for future Python releases.


range() and xrange() are functions. You are suggesting that 2
*functions* should acquire a __contains__ method each? I trust not.

Perhaps you meant that the acquisitors should be the objects that those
functions return.

range() returns a list. Lists already have a __contains__ method. It's
been getting a fair old exercising in the last few hours, but here we go
again:

Quote:
python -mtimeit -s"x=range(30000)" "x.__contains__(40000)"
1000 loops, best of 3: 1.09 msec per loop


Quote:
python -mtimeit -s"x=range(30000)" "40000 in x"
1000 loops, best of 3: 1.09 msec per loop


Quote:
python -mtimeit -s"x=range(30000)" "x.__contains__(1)"
1000000 loops, best of 3: 0.434 usec per loop


Quote:
python -mtimeit -s"x=range(30000)" "1 in x"
1000000 loops, best of 3: 0.137 usec per loop


A __contains__ method for xrange objects? The case of x in xrange(lo,
hi) is met by lo <= x < hi. IMHO, anyone who wants x in xrange(lo, hi,
step) should be encouraged to do the necessary algebra themselves; I
wouldn't suggest that any core dev time be wasted on implementing such
folderol.

In any case, isn't the *whole* xrange gizmoid on GvR's I-wish-I-hadn't list?

Cheers,
John
Back to top
Paul Boddie
*nix forums Guru Wannabe


Joined: 20 Feb 2005
Posts: 222

PostPosted: Tue Jul 18, 2006 12:24 pm    Post subject: Re: range() is not the best way to check range? Reply with quote

John Machin wrote:
Quote:

range() and xrange() are functions. You are suggesting that 2
*functions* should acquire a __contains__ method each? I trust not.

Well, range is a function in the current implementation, although its
usage is similar to that one would get if it were a class, particularly
a subclass of list or one providing a list-style interface. With such a
class, you could provide a __contains__ method which could answer the
question of what the range contains based on the semantics guaranteed
by a range (in contrast to a normal list).

Quote:
Perhaps you meant that the acquisitors should be the objects that those
functions return.

The whole point was to avoid expanding the range into a list.

[...]

Quote:
A __contains__ method for xrange objects? The case of x in xrange(lo,
hi) is met by lo <= x < hi. IMHO, anyone who wants x in xrange(lo, hi,
step) should be encouraged to do the necessary algebra themselves; I
wouldn't suggest that any core dev time be wasted on implementing such
folderol.

Sure, you could always implement your own class to behave like an
existing range and to implement the efficient semantics proposed above.

Quote:
In any case, isn't the *whole* xrange gizmoid on GvR's I-wish-I-hadn't list?

Yes, he wants range to return an iterator, just like xrange more or
less does now. Given that xrange objects support __getitem__, unlike a
lot of other iterators (and, of course, generators), adding
__contains__ wouldn't be much of a hardship. Certainly, compared to
other notational conveniences bounced around on the various development
lists, this one would probably provide an order of magnitude
improvement on the usual bang per buck development ratio.

Paul
Back to top
Stefan Behnel
*nix forums addict


Joined: 18 Apr 2005
Posts: 81

PostPosted: Tue Jul 18, 2006 12:42 pm    Post subject: Re: range() is not the best way to check range? Reply with quote

Andy Dingley wrote:
Quote:
The purpose of range() in Python is as loop control,

No, the purpose of range() is to create a list, as the docs state.

http://docs.python.org/lib/built-in-funcs.html

"""
range(...) - This is a versatile function to create lists containing
arithmetic progressions.
"""

Stefan
Back to top
Google

Back to top
Display posts from previous:   
Post new topic   Reply to topic Page 1 of 3 [43 Posts] Goto page:  1, 2, 3 Next
View previous topic :: View next topic
The time now is Sat Nov 22, 2008 12:01 am | All times are GMT
navigation Forum index » Programming » python
Jump to:  

Similar Topics
Topic Author Forum Replies Last Post
No new posts Rejecting connections based on IP range. Evil Ernie Exim 2 Thu Jul 20, 2006 8:54 pm
No new posts Force linker to check all the implementation toton C++ 1 Thu Jul 20, 2006 6:08 am
No new posts Qmail / SpamControl => Check if DNS exist ? Phibee NOC Qmail 2 Thu Jul 20, 2006 4:51 am
No new posts Power On Self Test Failed: Memory check Blk test failed BertieBigBollox@gmail.com Solaris 0 Wed Jul 19, 2006 9:48 am
No new posts How to check if a variable contains a " or ` ? Unix-Shell shell 1 Tue Jul 18, 2006 2:10 pm

Computers 2007 | Loans | Outsourcing | Web Games | Personal Loans
Copyright © 2004-2005 DeniX Solutions SRL
 
Other DeniX Solutions sites: Unix/Linux blog |  electronics forum |  medicine forum |  science forum | 
Privacy Policy


Powered by phpBB © 2001, 2005 phpBB Group
[ Time: 0.3625s ][ Queries: 16 (0.2241s) ][ GZIP on - Debug on ]