使用python&和数字计数的不同效率C

时间:2013-03-11 02:32:27

标签: python c performance python-2.7

我尝试编写一个计算数字位数的函数,顺便说一句,我尝试比较不同方式的效率。 1. lenstr(i)方式:

def nDigits(i):
    return len(str(i))
for i in range(100000):
    print nDigits(i)

需要大约143.75s

2. log10方式:

import math
def nDigits(i):
    if i > 0:
        n = int(math.log10(i)) + 1
    elif i == 0:
        n = 1
    else:
        n = int(math.log10(-i)) + 2
    return n

for i in range(100000):
    print nDigits(i)

需要大约144.35s

3.分工方式:

def nDigits(i):
    t = 0
    while i > 0:
        t += 1
        i /= 10
    return t
for i in range(100000):
    print nDigits(i)

需要大约143.43s

4. c中的划分方式:

#include<stdio.h>

int digits(int num){
    int i = 0;
    while (num > 0){
        i += 1;
        num /= 10;
    }
    return i;
} 

void main(){
    int i = 0;
    while (i < 100000){
        i += 1;
        printf("%d",digits(i));    
    }
}

大概需要0.07s

C是否比python好2000倍......或者python有更好的方法来计算数字位数。大家好,请帮我。

3 个答案:

答案 0 :(得分:1)

那很慢?如果您将for i in range(100000):更改为for i in xrange(100000):,则会更快,至少在我的计算机上(1秒或2或3)。

我怀疑使用range(100000)

会造成缓慢

xrange效率更高,因为它不是生成对象列表,而是一次只生成一个对象。在这种情况下,您应该优先于range

编辑:在@cge提到问题之后,我测试了你的原始代码(使用range(100000)),它也在一两秒内完成得很快,所以这可能不是你问题的原因(发生了一些可疑的事情,我从你在这里发布的代码中看不到,但我建议你使用xrange

答案 1 :(得分:1)

简化您的测试用例并删除所有print s:

import math

def num_digits1(n):
    return len(str(n))

def num_digits2(n):
    return int(math.log10(n)) + 1

def num_digits3(n):
    t = 0

    while n:
        t += 1
        n /= 10

    return t

以下是我的结果:

>>> %timeit num_digits1(random.randint(1, 100000000))
100000 loops, best of 3: 1.64 us per loop
>>> %timeit num_digits2(random.randint(1, 100000000))
100000 loops, best of 3: 1.87 us per loop
>>> %timeit num_digits3(random.randint(1, 100000000))
100000 loops, best of 3: 2.49 us per loop
>>> %timeit random.randint(1, 100000000)
1000000 loops, best of 3: 1.29 us per loop

减去生成随机数所需的时间,我得到:

num_digits1  0.35 us
num_digits2  0.58 us
num_digits3  1.20 us

我的C代码比较(我希望是公平的):

#include <stdlib.h>

int rand_int(int min, int max) {
    return min + (rand() / (double) RAND_MAX) / (max - min);
}

int num_digits(int num) {
    int i = 0;

    while (num > 0){
        i += 1;
        num /= 10;
    }

    return i;
} 

int main() {
    int i;

    for (i = 0; i < 10000000; i++) {
        num_digits(rand_int(1, 100000000));
    }

    return 0;
}

我跑了:

$ gcc test.c -o test
$ time ./test./test
0.15s user 0.00s system 97% cpu 0.154 total

我的时间是:

  0.154 s / 10,000,000
= 0.0154 us (0.0138 us with -O3)

C代码比Python解决方案快约23倍,这似乎很正常。希望我的C随机数生成器能够正常工作。

使用PyPy,66.7 ns获得us(不是num_digits1),这只慢了4.3倍。

答案 2 :(得分:1)

我认为你的瓶颈是印刷声明。请尝试将结果保存在列表中。

def nDigits(i):
    return len(str(i))
results = []
for i in xrange(1000000):
    results.append(nDigits(i))
print len(results)

我使用xrange代替range并添加了额外的0。它在我的机器上执行0.45秒。

使用列表理解将时间缩短到0.37秒。

def nDigits(i):
    return len(str(i))
results = [nDigits(i) for i in xrange(1000000)]
print len(results)

删除函数调用开销会使时间减少到0.31秒。

results = [len(str(i)) for i in xrange(1000000)]
print len(results)