Gibt es eine nicht schwebende Alternative zu pow ()?


9

Ich habe die SPRACHENREFERENZ auf der Arduino-Website durchsucht und kann kein Nicht-Float-Äquivalent finden, das bedeutet, dass pow() ich etwas Großes vermissen muss, aber für mein Leben bin ich ratlos! Ich habe pow()in der Spalte FUNCTIONS unter der Überschrift Math gefunden (wie ich es erwarten würde), aber es heißt, dass beide Parameter [base] und [exponent] beide sind (float). Und es gibt nur sechs weitere Einträge unter der Überschrift "Mathematik". Keiner von ihnen scheint eine ganzzahlige Version zu sein. Ich möchte nur die Potenzen von 2 mit den Exponenten von 0 bis 10 erzeugen. Wie 2 ^ 0 = 1, dann 2 ^ 1 = 2, dann 2 ^ 2 = 4, dann 2 ^ 3 = 8, dann 2 ^ 4 = 16 2 ^ 5 = 32 dann 2 ^ 6 = 64 dann 2 ^ 7 = 128 dann 2 ^ 8 = 256 dann 2 ^ 9 = 512 dann 2 ^ 10 ist 1024

Kann ich dies nur mit Floats tun? Ich fange an, mich im Widerspruch zur Realität zu fühlen und habe meine Medikamente tatsächlich gezählt, aber ich bin genau dort, wo ich sein sollte. Lassen Sie mich im Voraus für dieses ungeheure Versehen entschuldigen, mit dem ich Ihre Zeit verschwendet habe, aber ich habe alle 9 Seiten mit Tags durchgesehen und jemals gesucht, was mir einfiel. Ich gebe zu, dass ich nicht so viel Zeit verbracht habe, aber ich war mir sicher, dass dies nur eine fünfminütige Sache sein würde!


2
Den allgemeinen Fall von Integer pow () finden Sie unter stackoverflow.com/questions/101439/… . Verwenden Sie für Zweierpotenzen einfach Schichten.
Peter Cordes

Antworten:


8

Für den allgemeinen Fall ist die Antwort von @dat_ha richtig, aber es ist erwähnenswert, dass Sie einen ganz besonderen Fall wollen ... Zweierpotenzen. Da Computer binäre Arithmetik verwenden, stehen für Operationen mit Zweierpotenzen häufig einige Verknüpfungen zur Verfügung.

Das Multiplizieren einer Zahl mit einer Zweierpotenz kann durch die Linksverschiebungsoperation ( <<) erreicht werden, die die Ziffern der binären Darstellung der Zahl (dh der Bits) buchstäblich nach links verschiebt. In Basis zwei entspricht das Verschieben von Bits um eine Stelle nach links dem Multiplizieren mit 2, genau wie in Basis 10 das Verschieben von Ziffern um eine Stelle nach links dem Multiplizieren mit 10. Für eine vollständige Erläuterung des Linksverschiebungsoperators in C ++ Siehe diese Antwort unter Stapelüberlauf .

Es ist wichtig zu beachten, dass das Verschieben nach links Informationen verlieren kann. vom Ende verschobene Bits gehen verloren. Da Sie Potenzen von 2 bis 10 benötigen, sind Sie sicher, wenn Sie mit vorzeichenbehafteten Ganzzahlen arbeiten, die auf Arduino Uno einen Maximalwert von haben2^15-1 .

In Anbetracht dieser Einschränkungen ist hier eine Funktion zum Berechnen von Zweierpotenzen innerhalb dieser Einschränkungen. Dies ist ein sehr schneller Code, da die Linksverschiebungsoperation eine Operation mit sehr niedrigem Pegel ist und tatsächlich keine Multiplikation durchgeführt wird.

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

Fehler: Es kann bis zu 2 ^ 32 - 1 gehen, wenn Sie eine verwenden unsigned long.
Dat Ha

@DatHa danke, ich schien das Wort "signiert" während der Bearbeitung verloren zu haben. Fest.
Jason Clark

1
Es kann über 2 ^ 32 - 1 hinausgehen, wenn Sie eine Implementierung einer Ganzzahlarithmetik mit beliebiger Genauigkeit verwenden
Dat Han Bag

Ich möchte speziell wissen, warum die Ergebnisse einer Ganzzahlkonvertierung für die Ergebnisse von pow () NICHT für Potenzen von 2 funktionieren. Für mich gibt pow (2,3) 8,00 zurück, während int (8,00) 8 zurückgibt , int (pow (2,3)) gibt 7 zurück!
KDM

1

Es arbeitet mit int, double, longund float. unsigned longund unsigned intsollte auch funktionieren. Sie müssen NUR Floats verwenden.

Hoffe es hat geholfen!


Der Grund, warum die Antwort über der Antwort funktioniert, ist, dass die Menge der reellen Zahlen (die Gleitkommazahlen enthalten) die Menge der ganzen Zahlen enthält
Dat Han Bag

@DatHanBag: Und was noch wichtiger ist, jede 32-Bit-Ganzzahl kann genau durch a dargestellt werden double. Da das IEEE-Gleitkomma auf einer binären Mantisse / Exponent-Darstellung basiert, sollte jede Potenz von 2 auch über 2 ^ 53 hinaus genau darstellbar sein (der Punkt, an dem doublenicht jede beliebige ganze Zahl dargestellt werden kann, eine 1-Einheit an der letzten Stelle der Mantisse ist größer als 1,0).
Peter Cordes

@ PeterCordes Ja, das wusste ich. Vielleicht hätte ich in meinem Kommentar zur Antwort von
Dat Han Bag

4
Dies ist eine einigermaßen gültige Antwort auf die allgemeine Frage der Verwendung pow()für Ganzzahlen, aber AFAICT Arduino hat nicht einmal Hardware-Gleitkomma, daher ist es eine schreckliche Antwort. Eine ganze Zahl pow()Implementierung wie diese , dass Läufe in log2 (n) Zeit multipliziert wird und ein Ergebnis zu akkumulieren Zugabe würde wahrscheinlich an Sicherheit grenzender Wahrscheinlichkeit eine bessere Leistung, und das Unterlassen der Bit - Verschiebungen Arbeit für Potenzen von 2 zu erwähnen , macht gerade dies eine schreckliche Antwort auf diese Frage.
Peter Cordes

1
@ PeterCordes "also ist es eine schreckliche Antwort". -einverstanden, dass es eine Art einfache Antwort von geringer Qualität ist. pow () ist sicherlich in log2 (n) berechenbar - die einfache Methode, die in der Schule gelernt wurde (die Multiplikation der Zahl mit der Potenz ist nicht so effizient). Sie können es besser mit einer Fourier-Transformation für wirklich große ganze Zahlen machen - zum Beispiel. Aber vielleicht wird das OP es akzeptieren und mögen.
Dat Han Bag
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.