Чтобы проверить нечетное и четное целое число, самая низкая битная проверка более эффективна, чем использование modulo?
>>> def isodd(num):
return num & 1 and True or False
>>> isodd(10)
False
>>> isodd(9)
True
Чтобы проверить нечетное и четное целое число, самая низкая битная проверка более эффективна, чем использование modulo?
>>> def isodd(num):
return num & 1 and True or False
>>> isodd(10)
False
>>> isodd(9)
True
Угу. Модуль timeit
в стандартной библиотеке - это то, как вы проверяете эти вещи. Например:
AmAir:stko aleax$ python -mtimeit -s'def isodd(x): x & 1' 'isodd(9)'
1000000 loops, best of 3: 0.446 usec per loop
AmAir:stko aleax$ python -mtimeit -s'def isodd(x): x & 1' 'isodd(10)'
1000000 loops, best of 3: 0.443 usec per loop
AmAir:stko aleax$ python -mtimeit -s'def isodd(x): x % 2' 'isodd(10)'
1000000 loops, best of 3: 0.453 usec per loop
AmAir:stko aleax$ python -mtimeit -s'def isodd(x): x % 2' 'isodd(9)'
1000000 loops, best of 3: 0.461 usec per loop
Как вы видите, на моем (первый день == old == slow;-) Macbook Air решение &
повторяется между 7 и 18 наносекундами быстрее, чем решение %
.
timeit
не только скажет вам, что быстрее, но и сколько (просто запускайте тесты несколько раз), что обычно показывает, насколько это крайне важно (вам действительно интересно разницу в 10 наносекунд, когда накладные расходы вызов функции составляет около 400?! -)...
Убедительные программисты, которые, по сути дела, не оптимизируют микро-оптимизации, оказались невыполнимой задачей - хотя это было 35 лет (по сравнению с тем, что компьютеры получили порядок быстрее!), так как Knuth писал
Мы должны забыть о небольших эффективности, скажем, около 97% время: преждевременная оптимизация - это корень всего зла.
который, как он объяснил, является цитатой из еще более старого заявления Хора. Я думаю, что все полностью убеждены, что ИХ дело падает на оставшиеся 3%!
Поэтому вместо бесконечного повторения "это не имеет значения", мы (Тим Петерс, в частности, заслуживает там почестей) помещали в стандартный библиотечный модуль Python timeit
, что делает его тривиально простым для измерения таких микро-тестов и тем самым, по крайней мере, некоторые программисты убеждают себя в том, что, хм, этот случай попадает в группу 97%! -)
Чтобы быть абсолютно честным, Я не думаю, что это важно.
Первая проблема - читаемость. Что имеет смысл для других разработчиков? Я лично ожидал бы модулю при проверке четности/нечетности числа. Я ожидал бы, что большинство других разработчиков ожидали бы того же самого. Введя другой и неожиданный метод, вы можете сделать чтение кода и, следовательно, техническое обслуживание, более сложным.
Второй - это просто факт, что вы, вероятно, никогда не будете иметь узкое место при выполнении любой операции. Я для оптимизации, но ранняя оптимизация - самое худшее, что вы можете сделать на любом языке или в среде. Если по какой-то причине определение того, является ли число четным или нечетным, является узким местом, то найдите самый быстрый способ решения проблемы. Однако это возвращает меня к моему первому пункту - в первый раз, когда вы пишете рутину, это должно быть написано наиболее читаемым способом.
Лучшая оптимизация, которую вы можете получить, - не подвергать тест функции. "number % 2
" и "число и 1" - очень распространенные способы проверки четности/четности, опытные программисты сразу узнают шаблон, и вы всегда можете добавить комментарий, например "#, если число нечетное, тогда бла-бла-бла" если вам действительно нужно, чтобы это было очевидно.
# state whether number is odd or even
if number & 1:
print "Your number is odd"
else:
print "Your number is even"
"return num и 1 и True или False"? Вах! Если вы быстро сумасшедший (1) "return num и 1" (2) inline, он: if somenumber % 2 == 1
является разборчивым и битным isodd(somenumber)
, потому что он избегает вызова функции Python.
[email protected] ~> python -mtimeit -s'9 % 2'
10000000 loops, best of 3: 0.0271 usec per loop
[email protected] ~> python -mtimeit -s'10 % 2'
10000000 loops, best of 3: 0.0271 usec per loop
[email protected] ~> python -mtimeit -s'9 & 1'
10000000 loops, best of 3: 0.0271 usec per loop
[email protected] ~> python -mtimeit -s'9 & 1'
10000000 loops, best of 3: 0.0271 usec per loop
[email protected] ~> python -mtimeit -s'def isodd(x): x % 2' 'isodd(10)'
1000000 loops, best of 3: 0.334 usec per loop
[email protected] ~> python -mtimeit -s'def isodd(x): x % 2' 'isodd(9)'
1000000 loops, best of 3: 0.358 usec per loop
[email protected] ~> python -mtimeit -s'def isodd(x): x & 1' 'isodd(10)'
1000000 loops, best of 3: 0.317 usec per loop
[email protected] ~> python -mtimeit -s'def isodd(x): x & 1' 'isodd(9)'
1000000 loops, best of 3: 0.319 usec per loop
Интересно, что оба метода запоминают одно и то же время без вызова функции.
Помимо оптимизации зла, он убирает очень идиоматический "var% 2 == 0", который понимает каждый кодер, не глядя дважды. Таким образом, это нарушает питон zen, а также очень мало.
Кроме того, a = b и True или False были заменены для лучшей удобочитаемости с помощью
return True, если num и 1 else False
Был действительно удивлен, что ни один из вышеперечисленных ответов не установил обе переменные настройки (временный литерал - это разная история) и никакой вызов функции (который явно скрывает "нижние термины" ). Застрял на этом тайм-ауте от ipython timeit, где я получил явный победитель x & 1 - лучше на ~ 18%, используя python2.6 (~ 12%, используя python3.1).
На моей очень старой машине:
$ python -mtimeit -s 'x = 777' 'x&1'
10000000 loops, best of 3: 0.18 usec per loop
$ python -mtimeit -s 'x = 777' 'x%2'
1000000 loops, best of 3: 0.219 usec per loop
$ python3 -mtimeit -s 'x = 777' 'x&1'
1000000 loops, best of 3: 0.282 usec per loop
$ python3 -mtimeit -s 'x = 777' 'x%2'
1000000 loops, best of 3: 0.323 usec per loop