Preciso de uma função como esta:
// return true iff 'n' is a power of 2, e.g.
// is_power_of_2(16) => true is_power_of_2(3) => false
bool is_power_of_2(int n);
Alguém pode sugerir como eu poderia escrever isso? Você pode me dizer um bom site onde esse tipo de algoritmo pode ser encontrado?
c++
algorithm
bit-manipulation
Formiga
fonte
fonte
Respostas:
(n & (n - 1)) == 0
é melhor. No entanto, observe que ele retornará verdadeiro incorretamente para n = 0, portanto, se isso for possível, você desejará verificar isso explicitamente.http://www.graphics.stanford.edu/~seander/bithacks.html tem uma grande coleção de algoritmos de bit-twiddling inteligentes, incluindo este.
fonte
(n>0 && ((n & (n-1)) == 0))
n && !(n & (n - 1))
como o link nos estados de resposta.n & !(n & (n - 1))
. Observe o AND bit a bit&
(não lógico e&&
). Operadores bit a bit não implementam curto-circuito e, portanto, o código não se ramifica. Isso é preferível em situações em que as previsões erradas dos ramos são prováveis e quando o cálculo do rhs da expressão (ou seja,!(n & (n - 1))
) é barato.!
é um operador lógico e, portanto, o valor de!(n & (n - 1))
seria um booleano. Tem certeza de que um booleano e um número podem ser dados a um operador AND bit a bit? Se sim, parece bom.Uma potência de dois terá apenas um conjunto de bits (para números sem sinal). Algo como
Funcionará bem; um a menos que a potência de dois é todo 1s nos bits menos significativos, então deve fazer AND para 0 bit a bit.
Como eu estava assumindo números sem sinal, o teste == 0 (que originalmente esqueci, desculpe) é adequado. Você pode querer um teste> 0 se estiver usando números inteiros com sinal.
fonte
Potências de dois em binário são assim:
Observe que sempre há exatamente 1 bit definido. A única exceção é com um número inteiro assinado. por exemplo, um inteiro assinado de 8 bits com um valor de -128 se parece com:
Assim, depois de verificar se o número é maior que zero, podemos usar um pequeno truque inteligente para testar se um e apenas um bit está definido.
Para mais detalhes, veja aqui .
fonte
Abordagem # 1:
Divida o número por 2 reclusivamente para verificá-lo.
Complexidade de tempo: O (log2n).
Abordagem # 2:
E o número bit a bit com seu número anterior deve ser igual a ZERO.
Exemplo: Número = 8 Binário de 8: 1 0 0 0 Binário de 7: 0 1 1 1 e o AND bit a bit de ambos os números é 0 0 0 0 = 0.
Complexidade de tempo: O (1).
Abordagem # 3:
XOR bit a bit o número com seu número anterior deve ser a soma de ambos os números.
Exemplo: Número = 8 Binário de 8: 1 0 0 0 Binário de 7: 0 1 1 1 e o XOR bit a bit de ambos os números é 1 1 1 1 = 15.
Complexidade de tempo: O (1).
http://javaexplorer03.blogspot.in/2016/01/how-to-check-number-is-power-of-two.html
fonte
fonte
para qualquer potência de 2, o seguinte também é válido.
n & (- n) == n
NOTA: A condição é verdadeira para n = 0, embora não seja uma potência de 2. A
razão pela qual isso funciona é:
-n é o complemento de 2s de n. -n terá cada bit à esquerda do bit definido mais à direita de n invertido em comparação com n. Para potências de 2, há apenas um bit definido.
fonte
Em C ++ 20, existe o
std::ispow2
que você pode usar exatamente para essa finalidade se não precisar implementá-lo sozinho:fonte
Este é provavelmente o mais rápido, se estiver usando o GCC. Ele usa apenas uma instrução de cpu POPCNT e uma comparação. Representação binária de qualquer potência de 2 números, tem sempre apenas um conjunto de bits, os outros bits são sempre zero. Assim, contamos o número de bits definidos com POPCNT e, se for igual a 1, o número é a potência de 2. Não acho que haja métodos mais rápidos possíveis. E é muito simples, se você entendeu uma vez:
fonte
i && !(i & (i - 1)))
é cerca de 10% mais rápido na minha máquina, mesmo quando eu tinha certeza de habilitar a instrução POPCNT de assembly nativo no gcc.Seguir seria mais rápido do que a resposta mais votada devido ao curto-circuito booleano e ao fato de que a comparação é lenta.
Se você sabe que x não pode ser 0, então
fonte
fonte
Se você tiver um processador Intel moderno com as instruções de manipulação de bits , poderá executar o seguinte. Omite o código C / C ++ direto porque outros já responderam, mas você precisa dele se o IMC não estiver disponível ou ativado.
GCC, ICC e Clang sinalizam suporte para IMC com
__BMI__
. Ele está disponível em compiladores da Microsoft no Visual Studio 2015 e superior quando o AVX2 está disponível e ativado . Para os cabeçalhos de que você precisa, consulte Arquivos de cabeçalho para intrínsecos SIMD .Eu normalmente guardo o
_blsr_u64
com um_LP64_
caso compilando em i686. O Clang precisa de uma pequena solução alternativa porque usa um nome de símbolo intrínseco ligeiramente diferente:Este site é frequentemente citado: Bit Twiddling Hacks .
fonte
Este não é o caminho mais rápido ou curto, mas acho que é muito legível. Então, eu faria algo assim:
Isso funciona porque o binário é baseado em potências de dois. Qualquer número com apenas um bit definido deve ser uma potência de dois.
fonte
Aqui está outro método, neste caso usando em
|
vez de&
:fonte
É possível através de c ++
fonte
log2
, e a prova de que funciona não é tão fácil de explicar (precisamente, você pode ser pego por erros de arredondamento?). Também é desnecessariamente complicado comif..return..else..return
. O que há de errado em reduzi-loreturn x==(double)y;
? Ele deve retornarbool
anyayws. O IMO, mesmo o operador ternário, seria mais claro se alguém realmente quiser mantê-loint
.Sei que este é um post muito antigo, mas achei que poderia ser interessante postar aqui.
Da Code-Golf SE (portanto, todos os créditos para quem escreveu isso): Showcase of Languages
(Parágrafo sobre C , parágrafo Comprimento 36 fragmento )
fonte
Outra maneira (talvez não mais rápida) é determinar se ln (x) / ln (2) é um número inteiro.
fonte
Este é o método bit-shift em T-SQL (SQL Server):
É muito mais rápido do que fazer um logaritmo quatro vezes (primeiro conjunto para obter o resultado decimal, segundo conjunto para obter conjunto inteiro e comparar)
fonte