Existe uma alternativa não flutuante ao pow ()?

9

Eu vasculhei a REFERÊNCIA DE IDIOMA no site do Arduino e não consigo encontrar um equivalente que não seja do tipo Float para pow() que eu esteja perdendo algo grande, mas, para a minha vida, estou perplexo! Eu encontrei pow()na coluna FUNCTIONS sob o cabeçalho Math (como eu esperaria), mas diz que ambos os parâmetros, [base] e [expoente] são ambos (float). E há apenas seis outras entradas sob o cabeçalho Math; nenhum deles parece ser uma versão inteira. Tudo o que eu quero fazer é gerar os poderes de 2 usando os expoentes de 0 a 10. Como 2 ^ 0 = 1 então 2 ^ 1 = 2 então 2 ^ 2 = 4 então 2 ^ 3 = 8 então 2 ^ 4 = 16 então 2 ^ 5 = 32 então 2 ^ 6 = 64 então 2 ^ 7 = 128 então 2 ^ 8 = 256 então 2 ^ 9 = 512 então 2 ^ 10 é 1024

O uso de carros alegóricos é a única maneira de fazer isso? Estou começando a sentir que estou em desacordo com a realidade e, na verdade, contei minha medicação, mas estou exatamente onde deveria estar. Deixe-me desculpar-me antecipadamente por essa supervisão flagrante com a qual perdi seu tempo, mas passei por todas as 9 páginas de tags e fiz todas as pesquisas que consegui pensar. Admito que não passei tanto tempo assim, mas tinha certeza de que isso seria uma coisa de cinco minutos!

Bence Kaulics
fonte
2
Para o caso geral de número inteiro pow (), consulte stackoverflow.com/questions/101439/… . Para potências de 2, basta usar turnos.
Peter Cordes

Respostas:

8

Para o caso geral, a resposta de @dat_ha está correta, mas vale a pena notar que você deseja um caso muito especial ... potências de dois. Como os computadores usam aritmética binária, as operações que envolvem potências de dois geralmente têm alguns atalhos disponíveis.

A multiplicação de um número por uma potência de dois pode ser realizada pela operação de deslocamento à esquerda ( <<), que literalmente muda os dígitos da representação binária do número (ou seja, bits) para a esquerda. Na base dois, mudar os bits de um lugar para a esquerda é o mesmo que multiplicar por 2, assim como na base 10 os dígitos de deslocamento um lugar para a esquerda é o mesmo que multiplicar por 10. Para obter uma explicação completa do operador de deslocamento à esquerda em C ++ , consulte esta resposta no Stack Overflow .

É importante observar que o deslocamento para a esquerda pode perder informações; bits deslocados no final são perdidos. Como você precisa de potências de 2 a 10, você está seguro ao trabalhar com números inteiros assinados, com um valor máximo 2^15-1no Arduino Uno .

Dadas essas advertências, aqui está uma função para calcular potências de duas dentro dessas restrições. Este é um código muito rápido, porque a operação de deslocamento à esquerda é uma operação de nível muito baixo e nenhuma multiplicação é realmente executada.

int pow2(int p){
    return 1 << p;
}
Jason Clark
fonte
Erro: pode ir até 2 ^ 32 - 1 se você usar um unsigned long.
Dat Ha
@DatHa obrigado, parecia que perdi a palavra "assinado" durante a edição. Fixo.
Clark Clark
11
Ele pode ir passado 2 ^ 32 - 1, se você usar uma implementação de precisão arbitrária inteiro aritmética
Dat Han Bag
Gostaria de saber especificamente por que os resultados de uma conversão inteira nos resultados de pow () NÃO funcionam com potências de 2. Para mim, pow (2,3) retorna 8,00, mas enquanto int (8,00) retorna 8 , int (pow (2,3)) retorna 7!
KDM
1

Ele funciona com int, double, longe float. unsigned longe unsigned inttambém deve funcionar. Você não é obrigado a usar APENAS carros alegóricos.

Espero que tenha ajudado!

Dat Ha
fonte
A razão a resposta acima resposta funciona é porque o conjunto dos números reais (que contêm floats) contém o conjunto de inteiros
Dat Han Bag
@DatHanBag: E mais importante, todo número inteiro de 32 bits é exatamente representável por a double. Na verdade, como o ponto flutuante IEEE é baseado em uma representação binária de mantissa / expoente, toda potência de 2 deve ser exatamente representável até além de 2 ^ 53 (o ponto em doubleque não pode representar todo número inteiro arbitrário, uma unidade no último lugar do mantissa é maior que 1,0).
Peter Cordes
@ PeterCordes Sim, eu sabia disso. Talvez eu devesse ter dito "conjuntos limitados" quando se refere a flutuar e conjuntos inteiros para arduino no meu comentário sobre a resposta de
Dat Han Bag
4
Esta é uma resposta um tanto válida para a questão geral do uso pow()de números inteiros, mas o AFAICT arduino nem tem ponto flutuante de hardware, por isso é uma resposta terrível. Uma pow()implementação inteira como esta que é executada no tempo log2 (n) multiplicando e adicionando para acumular um resultado provavelmente certamente teria um desempenho melhor, e deixar de mencionar que a troca de bits funciona para potências de 2 apenas faz desta uma péssima resposta a esta pergunta.
Peter Cordes
11
@ PeterCordes "por isso é uma resposta terrível". - concordou que é uma resposta simplista de baixa qualidade. pow () é certamente computável no log2 (n) - o método simples aprendido na escola (multiplicar o número por si só ao poder não é tão eficiente). Você pode fazer isso melhor com uma transformação de Fourier para números realmente grandes, por exemplo. Mas talvez o OP aceite e goste.
Dat Han Bag