I was playing around with big numbers, and wrote the following code:
import time
def ispow2(n):
return not n & n - 1
start = time.clock()
ispow2(2**100000000)
end = time.clock()
print(end - start)
Surprisingly, this outputs 0.016864107385627148, and insanely short amount of time. However, it actually takes about 8 seconds, not 0.02.
Why is the time module reporting such a fast time when it clearly takes longer than that to run the code?
According to time, clock() is deprecated, so I switched it out for process_time(). I get near identical results. Same with perf_counter().
Note: this is running from IDLE. When I ran from command line, the time seemed accurately reported. Perhaps pythonw.exe has something to do with this, but what?
However, when I add another 0 to the end of 2**10..., it takes ~7 seconds on command line, but reported 0.1781140373572865.
python.exe and pythonw.exe are optimizing the code before running. It seems that the 2**100000000 is being pre-computed. This small edit to the code:
import time
print("program entered")
def ispow2(n):
return not n & n - 1
start = time.perf_counter()
ispow2(2**100000000)
end = time.perf_counter()
print(end - start)
Produces the following output completely after the wait:
program entered
0.01701506924359556
So the program doesn't even run until after the majority of the wait.
Data that suggests that this is with the 2**... part (running from command line):
power of two|approximate wait time|reported time
1000000000 | 6 seconds |0.1637752267742188
10000000000 | 62 seconds |1.6400543291627092
On that last run, there was a clear ~1.5 second wait between the output of program entered and 1.6400543291627092.
The constant is precomputed:
>>> import dis
>>> dis.dis(lambda: 2**100)
1 0 LOAD_CONST 3 (1267650600228229401496703205376)
3 RETURN_VALUE
Compare:
$ ./python -mtimeit "2**1000"
10000000 loops, best of 3: 0.0601 usec per loop
$ ./python -mtimeit "2**10000"
10000000 loops, best of 3: 0.0584 usec per loop
vs.:
$ ./python -mtimeit -s "p=1000" "2**p"
100000 loops, best of 3: 6.89 usec per loop
$ ./python -mtimeit -s "p=10000" "2**p"
10000 loops, best of 3: 94.2 usec per loop
In the first case the time doesn't change after increasing the power 10 times. It is changed as it should in the second case there the power is a variable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With