Existe-t-il une alternative non flottante à pow ()?

9

J'ai parcouru la RÉFÉRENCE LINGUISTIQUE sur le site Web d'Arduino , et je ne trouve pas d'équivalent non flottant pow() car je dois manquer quelque chose de gros, mais pour la vie de moi, je suis perplexe! J'ai trouvé pow()dans la colonne FONCTIONS sous l'en-tête Math (comme je m'y attendrais), mais il dit que les deux paramètres, [base] et [exposant] sont tous les deux (float). Et il n'y a que six autres entrées sous le titre Math; aucun d'eux ne semble être une version entière. Tout ce que je veux faire, c'est générer les puissances de 2 en utilisant les exposants de 0 à 10. Comme 2 ^ 0 = 1 puis 2 ^ 1 = 2 puis 2 ^ 2 = 4 puis 2 ^ 3 = 8 puis 2 ^ 4 = 16 puis 2 ^ 5 = 32 puis 2 ^ 6 = 64 puis 2 ^ 7 = 128 puis 2 ^ 8 = 256 puis 2 ^ 9 = 512 puis 2 ^ 10 est 1024

Est-ce que l'utilisation de flotteurs est la seule façon de le faire? Je commence à avoir l'impression d'être en désaccord avec la réalité et d'avoir effectivement compté mes médicaments, mais je suis là où je devrais être. Permettez-moi de m'excuser à l'avance pour cette omission flagrante avec laquelle j'ai perdu votre temps, mais j'ai parcouru les 9 pages de balises et j'ai fait toutes les recherches auxquelles je pouvais penser. J'avoue que je n'ai pas passé autant de temps, mais j'étais sûr que ça ne serait que cinq minutes!

Bence Kaulics
la source
2
Pour le cas général de pow entier (), voir stackoverflow.com/questions/101439/… . Pour les puissances de 2, utilisez simplement les changements.
Peter Cordes

Réponses:

8

Pour le cas général, la réponse de @dat_ha est correcte, mais il convient de noter que vous voulez un cas très spécial ... des pouvoirs de deux. Parce que les ordinateurs utilisent l'arithmétique binaire, les opérations impliquant des puissances de deux ont souvent des raccourcis disponibles.

La multiplication d'un nombre par une puissance de deux peut être accomplie par l'opération de décalage vers la gauche ( <<), qui décale littéralement les chiffres de la représentation binaire du nombre (c'est-à-dire des bits) vers la gauche. Dans la base deux, décaler les bits d'un endroit vers la gauche équivaut à multiplier par 2, tout comme dans la base 10, décaler les chiffres d'un endroit vers la gauche équivaut à multiplier par 10. Pour une explication complète de l'opérateur de décalage gauche en C ++ , voir cette réponse sur Stack Overflow .

Il est important de noter que le décalage à gauche peut perdre des informations; les bits décalés à la fin sont perdus. Parce que vous avez besoin de puissances de 2 à 10, vous êtes en sécurité lorsque vous travaillez avec des entiers signés, qui ont une valeur maximale de 2^15-1Arduino Uno .

Compte tenu de ces mises en garde, voici une fonction pour calculer les puissances de deux dans ces contraintes. Il s'agit d'un code très rapide car l'opération de décalage vers la gauche est une opération de très bas niveau et aucune multiplication n'est réellement effectuée.

int pow2(int p){
    return 1 << p;
}
Jason Clark
la source
Erreur: il peut aller jusqu'à 2 ^ 32 - 1 si vous utilisez un unsigned long.
Dat Ha
@DatHa merci, il me semblait avoir perdu le mot "signé" lors de l'édition. Fixé.
Jason Clark
1
Il peut dépasser 2 ^ 32 - 1 si vous utilisez une implémentation d'arithmétique d'entiers de précision arbitraire
Dat Han Bag
J'aimerais, en particulier, savoir pourquoi les résultats d'une conversion entière sur les résultats de pow () NE FONCTIONNENT PAS pour des puissances de 2. Pour moi, pow (2,3) renvoie 8,00, mais tandis que int (8,00) renvoie 8 , int (pow (2,3)) renvoie 7!
KDM
1

Il fonctionne avec int, double, longet float. unsigned longet unsigned intdevrait également fonctionner. Vous n'êtes pas obligé d'utiliser UNIQUEMENT des flotteurs.

J'espère que cela a aidé!

Dat Ha
la source
La raison pour laquelle la réponse ci-dessus fonctionne est parce que l'ensemble des nombres réels (qui contiennent des flottants) contient l'ensemble des entiers
Dat Han Bag
@DatHanBag: Et plus important encore, chaque entier 32 bits est exactement représentable par a double. En fait, puisque le point flottant IEEE est basé sur une représentation mantisse / exposant binaire, chaque puissance de 2 devrait être exactement représentable même au-delà de 2 ^ 53 (le point où doublene peut pas représenter chaque entier arbitraire, une unité de 1 à la dernière place de la mantisse est supérieure à 1,0).
Peter Cordes
@PeterCordes Oui, je le savais. Peut-être aurais-je dû dire "ensembles bornés" en faisant référence aux ensembles flottants et entiers pour arduino dans mon commentaire sur la réponse de
Dat Han Bag
4
C'est une réponse quelque peu valable à la question générale de l'utilisation pow()des entiers, mais AFAICT arduino n'a même pas de virgule flottante matérielle, c'est donc une réponse terrible. Une pow()implémentation entière comme celle-ci qui s'exécute en log2 (n) multipliant le temps et ajoutant pour accumuler un résultat serait probablement plus performante, et à défaut de mentionner que les décalages de bits fonctionnent pour des puissances de 2, c'est juste une réponse terrible à cette question.
Peter Cordes
1
@PeterCordes "c'est donc une réponse terrible". - a reconnu qu'il s'agit d'une sorte de réponse simpliste de faible qualité. pow () est certainement calculable dans log2 (n) - la méthode simple apprise à l'école (multiplier le nombre par lui-même à la puissance n'est pas si efficace). Vous pouvez le faire mieux avec une transformée de Fourier pour les très grands entiers, par exemple. Mais peut-être que le PO l'acceptera et l'aimera.
Dat Han Bag