Эта статья посвящена одной из наипопулярнейших задач в области программирования. Сложно представить себе программиста, который хотя бы раз в своей карьере не сталкивался с ней.
Существует целый ряд способов её решения. В этой статье будут рассмотрены два, наиболее грамотные из них.
Данные методы считаются таковыми не только в силу своей вычислительной эффективности, но и прежде всего потому, что имеют объективное математическое обоснование.
1.Использование битовых операций
Delphi/Pascal
n and ( n — 1 ) = 0
Или в варианте C++ и ему подобных языков
n
if ( n > 1 ) then
if n and ( n — 1 ) = 0 then
WriteLn ( ‘Yes’ )
WriteLn ( ‘No’ ) ;
Или в варианте для C++:
if ( ( n Yes» ) ;
printf ( «No» ) ;
2.Использование логарифмов
Этот способ уже был подробно описан в статье «Является ли число степенью другого числа». В данном способе задача проверки, является ли число степенью двойки, рассматривается как частный случай задачи рассмотренной там.
C++: Лабораторная по рекурсии — проверка на степень двойки
Для выполнения проверки необходимо вычислить логарифм числа по основанию 2 или частное логарифмов проверяемого числа и числа 2 по общему основанию и проверить является ли результат целым числом.
Если используемый язык программирования или библиотека имеют готовую функцию для вычисления логарифма по основанию 2, решение упрощается до предела.
Источник: streletzcoder.ru
Как определить, является ли число степенью двойки на python3?
Проблема в том, что log(16, 2) # = 4.0 по мнению интерпретатора не является целым числом.
Как можно по другому проверить является ли n степенью двойки?
- Вопрос задан более трёх лет назад
- 23285 просмотров
Комментировать
Решения вопроса 2
Ох..но, проверять степень двойки с помощью логарифма.
Вот вам идея для решения попроще: n — побитовое «и»).
Ответ написан более трёх лет назад
Нравится 2 1 комментарий
Спасибо большое.
n = 16 from math import log Logn = log(n, 2) if (Logn == int(Logn)): print «True» else: print «False»
Ответ написан более трёх лет назад
Комментировать
Нравится Комментировать
Ответы на вопрос 2
Умею рисовать тени
return x ((x Гугл отключили?
Ответ написан более трёх лет назад
Нравится 1 1 комментарий
Бляха дошутитесь так и рил отрубят от гуглсервисов
Drugs-driven development
Тебе же в прошлом вопросе разжевали всё, зачем снова плодить глупые вопросы? Но если ты прошлый вопрос спрашивал, чтобы таким образом проверять на степень двойки, то лучше сразу уходи их профессии. Изучи хотя бы основы построения алгоритмов.
Java — урок 16.3 (Integer.bitCount — является ли число с основанием два)
Нормальная и быстрая проверка на степень двойки делается через бинарные операции:
def check2rec(num): if num == 1: return True if num > 1)
Плюс, эту функцию можно ещё пооптимизировать.
Ну и бенчмарки, чтобы доказать ущербность логарифмического метода:
def check2rec(num): if num == 1: return True if num > 1) def check2log(num): r = log(num, 2) return int(r) == r numbers = list() print(‘Generating numbers. ‘) for _ in range(1000): numbers.append(randint(10000, 1000000)) print(‘Done!’) start = datetime.datetime.now() for _ in range(10000): for n in numbers: check2rec(n) print(‘Rec: ‘, datetime.datetime.now() — start) start = datetime.datetime.now() for _ in range(10000): for n in numbers: check2log(n) print(‘Log: ‘, datetime.datetime.now() — start)
Результаты:
Rec: 0:00:07.408942 Log: 0:00:12.101660
Разница почти в 2 раза.
P.S. С такими «знаниями» тебя в более-менее приличное место не возьмут никогда. Изучи сперва программирование (т.е. построение алгоритмов), а не язык. Почитай Вирта, Кормена, или SICP.
Источник: qna.habr.com
Битовые операции I: битовые поля, степень двойки
Решил выложить накопленный материал по реализации некоторых операций с помощью стандартных операторов C. Планируется три части. Данный материал довольно легко найти на английском языке, и некоторые ссылки на источники я здесь размещу.
Предполагается, что читатель осведомлён о том, что такое поразрядные операции, и какие из них доступны в стандартном C. Стандартные целочисленные типы заданной ширины определены в stdint.h (cstdint в C++, «int» в случае C++ можно заменить на bool). Тип «unsigned» используется, чтобы показать отсутствие конкретных требований по разрядности параметра.
Так как во многих случаях описанные операции поддерживаются современными процессорами непосредственно, компиляторы предоставляют реализующие их специальные нестандартные функции («intrinsics» или «builtins»). Если целевой процессор поддерживает нужные команды, то при использовании интринсиков компилятор будет транслировать код в эти команды. К сожалению, не всегда гарантируется автоматическая подмена неподдерживаемых команд программными реализациями, поэтому при написании кроссплатформенного кода могут понадобиться собственные «заменители» для общего случая. Да и не всегда хочется отягощать код использованием интринсиков.
Простейшие манипуляции
Проверить значение заданного бита
Данное действие выполнить весьма просто: нужно установить бит с заданным номером, что легко достигается с помощью операции сдвига влево, и использовать полученное значение как маску.
inline int test_bit(unsigned word, unsigned bit)
Ассемблерные аналоги x86: BT.
Изменить значение заданного бита
Следующие четыре функции возвращают новое значение слова (с изменённым битом в заданной позиции):
// Установить заданный бит inline unsigned set_bit(unsigned word, unsigned bit) < return word | (1u // Сбросить заданный бит inline unsigned reset_bit(unsigned word, unsigned bit) < return word return word ^ (1u // Установить заданный бит в заданное значение inline unsigned set_bit( unsigned word, unsigned bit, int value)
Ассемблерные аналоги x86: BTS, BTR, BTC.
Извлечь битовое поле
Итак, операцией поразрядного сдвига влево можно установить бит в заданной позиции. Если теперь вычесть единицу, то получим битовую строку, в которой установлены все биты в позициях правее ранее установленного бита.
unsigned mask = (1u
Теперь можно сдвинуть полученную таким образом маску влево, чтобы установленные биты совпали с битами, стоящими в желаемых позициях (битовым полем). Под «битовым полем» в данном примере понимается непрерывный фрагмент машинного слова (например, все биты с 5-го по 10-й включительно).
Пусть задан номер начального бита, принадлежащего битовому полю (start), и количество бит, входящих в битовое поле (length; соответственно, все биты с 5-го по 10-й включительно: start = 5, length = 6). Тогда извлечь значение битового поля в виде беззнакового целого можно следующей функцией:
inline unsigned get_bitfield( unsigned word, unsigned start, unsigned length) < return (word >> start) ~(P – 1).
inline unsigned round_up_to_pow2(unsigned x, unsigned pow2) < unsigned pow2m1 = pow2 — 1; // pow2 обязано быть степенью двойки assert((pow2 return (x + pow2m1) >
Вычислить ближайшую сверху степень двойки
Требуется вычислить число, равное степени двойки, не меньшей, чем заданное натуральное число. Данную операцию реализовать сложнее, чем предыдущие. Ниже приведена реализация для 32-битного числа (позаимствовано отсюда).
inline uint32_t round_up_to_pow2(uint32_t x) < —x; x |= x >> 1; // Группа наложений-сдвигов эффективно x |= x >> 2; // заменяет линейную последовательность вида x |= x >> 4; // x |= x >> 1; x |= x >> 2; x |= x >> 3; . x |= x >> 8; // x |= x >> 31; x |= x >> 16; // На каждое удвоение разрядности достаточно return x + 1; // добавлять одну такую строчку. >
Впрочем, если имеется эффективная реализация функции leading_zero_bits, подсчитывающей количество идущих подряд старших нулей (можно реализовать её на основе команд x86 BSR или (ABM/BMI) LZCNT, в дальнейшем я планирую привести реализацию на основе стандартных операций), то можно использовать её:
inline unsigned round_up_to_pow2(unsigned x)
Источник: evetro.wordpress.com