2013-05-28 5 views
3

Академический вопрос. Эта функция вычисляет Benford's Law для целых чисел до maxvalue и печатает сводную таблицу. Я пробовал вложенный метод for-loop, метод dict и этот метод коллекций. Последний (код ниже) кажется самым быстрым (результат timeit: 1.4852424694 сек), но есть ли более быстрый и эффективный с точки зрения памяти метод для циклирования через так много возможностей?Более эффективный код закона Бенфорда?

from __future__ import print_function 
def BenfordsLaw4(maxvalue = 10**6): 
    from collections import Counter 
    sqList = (str((i+1)**2)[0] for i in range(maxvalue)) 
    BenfordList = Counter(sqList) 

    print("Benford's Law for numbers between 1 and", maxvalue, "\nDigits,\t\t\t", "Count,\t\t\t", "Percentage") 
    for i,j in sorted(BenfordList.iteritems()): 
     print(',\t\t\t\t'.join([str(i), str(j), str(j*100./maxvalue)+' %'])) 
+0

Каковы были времена для других методов? – mtrw

+1

В Python 2.7, 'xrange' может быть немного быстрее, чем' range', и определенно будет более эффективным с точки зрения памяти. – Gabe

+0

Что там делает '** 2'? Вероятно, это займет большую часть времени и заставит вас измерить полномочия от 2 до 2^1 000 000, а не целых до 1 000 000. – Gabe

ответ

1

Изменение основного цикла к следующему:

def BenfordsLaw4(maxvalue = 10**6): 
    BenfordList = {str(i+1):0 for i in range(9)} 
    for i in (str((i+1)**2)[0] for i in xrange(maxvalue)): 
     BenfordList[i] += 1 

занимает время от примерно 1.55s до примерно 1,25; однако вынос **2 занимает время примерно до 0,32 с.

Другими словами, подавляющее большинство вашего времени потрачено на возведение в квадрат ваших операндов.

Любопытно, что мне удалось сбрить около 0,05 с помощью "%s" % ((i+1)**2) вместо str((i+1)**2).

+0

Sweet! Я понял, что основная часть времени потрачена на создание чисел (например, функции или чтения данных), но мне очень нравится, что ваш ответ быстрее (1.2564006048 сек) и позволяет избежать импорта специального метода. – ksed

+0

Может просто изменить диапазон на 'range (1, 10)' и избежать '+ 1' ops –

Смежные вопросы