Esiste un'alternativa non float a pow ()?


9

Ho analizzato il RIFERIMENTO LINGUISTICO nel sito web di Arduino e non riesco a trovare un equivalente non galleggiante che pow() mi manca per qualcosa di grosso, ma per la vita di me sono sconcertato! Ho trovato pow()nella colonna FUNZIONI sotto l'intestazione matematica (come mi sarei aspettato), ma dice che entrambi i parametri, [base] ed [esponente] sono entrambi (float). E ci sono solo altre sei voci sotto l'intestazione matematica; nessuno di loro sembra essere una versione intera. Tutto quello che voglio fare è generare i poteri di 2 usando gli esponenti da 0 a 10. Come 2 ^ 0 = 1 quindi 2 ^ 1 = 2 quindi 2 ^ 2 = 4 quindi 2 ^ 3 = 8 quindi 2 ^ 4 = 16 quindi 2 ^ 5 = 32 quindi 2 ^ 6 = 64 quindi 2 ^ 7 = 128 quindi 2 ^ 8 = 256 quindi 2 ^ 9 = 512 quindi 2 ^ 10 è 1024

L'uso dei float è l'unico modo per farlo? Sto iniziando a sentirmi in contrasto con la realtà e in realtà ho contato le mie medicine, ma sono proprio dove dovrei essere. Vorrei scusarmi in anticipo per questa svista egregia con la quale ho perso tempo, ma ho esaminato tutte e 9 le pagine di tag e ho fatto qualsiasi ricerca mi venisse in mente. Devo ammettere che non ho trascorso tutto quel tempo, ma ero sicuro che sarebbe stata solo una cosa da cinque minuti!


2
Per il caso generale di integer pow (), consultare stackoverflow.com/questions/101439/… . Per potenze di 2, basta usare i turni.
Peter Cordes,

Risposte:


8

Per il caso generale, la risposta di @dat_ha è corretta, ma vale la pena notare che si desidera un caso molto speciale ... potenze di due. Poiché i computer utilizzano l'aritmetica binaria, le operazioni che comportano potenze di due hanno spesso alcune scorciatoie disponibili.

Moltiplicare un numero per una potenza di due può essere ottenuto dall'operazione di spostamento a sinistra ( <<), che sposta letteralmente le cifre della rappresentazione binaria del numero (cioè, bit) verso sinistra. Nella base due, spostare i bit di un posto a sinistra equivale a moltiplicare per 2, proprio come nella base 10 spostare le cifre di un posto a sinistra equivale a moltiplicare per 10. Per una spiegazione completa dell'operatore di spostamento a sinistra in C ++ , vedi questa risposta su Stack Overflow .

È importante notare che lo spostamento a sinistra può perdere informazioni; i bit spostati dall'estremità vengono persi. Poiché hai bisogno di potenze da 2 a 10, sei al sicuro quando lavori con numeri interi con segno, che hanno un valore massimo di 2^15-1su Arduino Uno .

Date queste avvertenze, ecco una funzione per calcolare i poteri di due all'interno di questi vincoli. Questo è un codice molto veloce perché l'operazione di spostamento a sinistra è un'operazione di livello molto basso e in realtà non viene eseguita alcuna moltiplicazione.

int pow2(int p){
    return 1 << p;
}

Errore: può andare fino a 2 ^ 32 - 1 se si utilizza un unsigned long.
Dat Ha,

@DatHa grazie, mi sembrava di aver perso la parola "firmato" durante il montaggio. Fisso.
Jason Clark,

1
Può andare oltre 2 ^ 32 - 1 se si utilizza un'implementazione dell'aritmetica di numeri interi di precisione arbitraria
Dat Han Bag

Vorrei, in particolare, sapere perché i risultati di una conversione intera sui risultati di pow () NON funzionano per potenze di 2. Per me, pow (2,3) restituisce 8,00, ma mentre int (8,00) restituisce 8 , int (pow (2,3)) restituisce 7!
KDM,

1

Funziona con int, double, longe float. unsigned longe unsigned intdovrebbe anche funzionare. Non è necessario utilizzare SOLO float.

Spero che abbia aiutato!


Il motivo per cui funziona la risposta sopra è perché l'insieme di numeri reali (che contengono float) contiene l'insieme di numeri interi
Dat Han Bag

@DatHanBag: E, soprattutto, ogni numero intero a 32 bit è esattamente rappresentabile da a double. In realtà, poiché il punto in virgola mobile IEEE si basa su una rappresentazione binaria di mantissa / esponente, ogni potenza di 2 dovrebbe essere esattamente rappresentabile anche oltre 2 ^ 53 (il punto in cui doublenon può rappresentare ogni numero intero arbitrario, 1 unità all'ultimo posto del mantissa è maggiore di 1.0).
Peter Cordes,

@PeterCordes Sì, lo sapevo. Forse avrei dovuto dire "insiemi limitati" quando mi riferivo a insiemi float e interi per arduino nel mio commento sulla risposta di
Dat Han Bag

4
Questa è una risposta in qualche modo valida alla domanda generale sull'uso pow()degli interi, ma AFAICT arduino non ha nemmeno un virgola mobile hardware, quindi è una risposta terribile. Un numero intero pow()implementazione come questo che viene eseguito in log2 (n) moltiplicando e l'aggiunta di accumulare un risultato quasi certamente probabilmente un rendimento migliore, e non riuscendo a ricordare che il lavoro bit turni per potenze di 2 fa solo questo una risposta terribile a questa domanda.
Peter Cordes,

1
@PeterCordes "quindi è una risposta terribile". - ha convenuto che è una specie di risposta semplicistica di bassa qualità. pow () è certamente calcolabile in log2 (n) - il semplice metodo appreso a scuola (moltiplicare il numero da solo per il potere non è così efficiente). Puoi farlo meglio con una trasformata di Fourier per numeri interi davvero grandi, ad esempio. Ma forse l'OP accetterà e piacerà.
Dat Han Bag,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.