1

我尝试编写一个函数来计算数字位数,顺便说一下,我尝试比较不同方式的效率。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.35 秒

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有更好的方法来计算数字。thx伙计们,请帮助我。

4

3 回答 3

1

这么慢??如果您更改for i in range(100000):for i in xrange(100000):,它会快得多,至少在我的计算机上(1 秒或 2 或 3 秒)。

我怀疑缓慢是由于您使用range(100000)

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

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

于 2013-03-11T02:38:05.647 回答
1

简化您的测试用例并删除所有这些print

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) for num_digits1,它只慢了 4.3 倍。

于 2013-03-11T02:54:32.943 回答
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)
于 2013-03-11T02:55:09.043 回答