Ich lerne in letzter Zeit schnell, aber ich habe ein grundlegendes Problem, das keine Antwort finden kann
Ich möchte so etwas bekommen
var a:Int = 3
var b:Int = 3
println( pow(a,b) ) // 27
Aber die pow-Funktion kann nur mit doppelter Zahl arbeiten, sie funktioniert nicht mit ganzzahliger Zahl, und ich kann das int nicht einmal durch Double (a) oder a.double () in double umwandeln ...
Warum liefert es nicht die Potenz der ganzen Zahl? es wird definitiv eine ganze Zahl ohne Mehrdeutigkeit zurückgeben! und warum kann ich keine ganze Zahl in ein Doppel umwandeln? es ändert sich nur 3 zu 3.0 (oder 3.00000 ... was auch immer)
Wie kann ich es reibungslos machen, wenn ich zwei Ganzzahlen habe und die Energieoperation ausführen möchte?
Vielen Dank!
Antworten:
Wenn Sie möchten, können Sie dies erklären
infix
operator
.Ich habe zwei Carets verwendet, damit Sie weiterhin den XOR-Operator verwenden können .
Update für Swift 3
In Swift 3 wird die "magische Zahl"
precedence
ersetzt durchprecedencegroups
:quelle
infix operator ^^ { precedence 160 } func ^^
... und so weiterfunc p(_ b: Bool) -> Double { return b?-1:1 }
?Abgesehen davon, dass Ihre Variablendeklarationen Syntaxfehler aufweisen, funktioniert dies genau so, wie Sie es erwartet haben. Alles was Sie tun müssen, ist zu werfen
a
undb
zu verdoppeln und die Werte an zu übergebenpow
. Wenn Sie dann mit 2 Ints arbeiten und ein Int wieder auf der anderen Seite der Operation haben möchten, kehren Sie einfach zu Int zurück.quelle
3 ** 3
. Manchmal muss ich das Algorithmusproblem mit Swift lösen, es ist wirklich schmerzhaft im Vergleich zur Verwendung von Python.Manchmal ist das Casting von a
Int
zu aDouble
keine praktikable Lösung. Bei einigen Größen gibt es einen Genauigkeitsverlust bei dieser Umwandlung. Der folgende Code gibt beispielsweise nicht das zurück, was Sie intuitiv erwarten könnten.Wenn Sie Präzision bei hohen Größen benötigen und sich keine Gedanken über negative Exponenten machen müssen - die im Allgemeinen ohnehin nicht mit ganzen Zahlen gelöst werden können -, ist diese Implementierung des Algorithmus für die rekursive Exponentiation durch Quadrieren die beste Wahl. Nach dieser SO-Antwort ist dies "die Standardmethode für die modulare Exponentiation für große Zahlen in der asymmetrischen Kryptographie".
Hinweis: In diesem Beispiel habe ich ein Generikum verwendet
T: BinaryInteger
. Dies ist , so können Sie verwenden ,Int
oderUInt
oder eine beliebige andere ganze Zahl artigen Typ.quelle
Int
oder Sie können diese Dinge diese freie Funktion nennen lassen - was auch immer Ihr Herz begehrt.Wenn Sie wirklich eine "Nur Int" -Implementierung wünschen und nicht zu / von zwingen
Double
müssen, müssen Sie sie implementieren. Hier ist eine triviale Implementierung; Es gibt schnellere Algorithmen, aber das wird funktionieren:In einer realen Implementierung möchten Sie wahrscheinlich eine Fehlerprüfung.
quelle
Double(Int.max - 1) < Double(Int.max)
in einem Swift 3 REPL zu laufen, und Sie werden überrascht sein.reduce
Aufruf implementieren .return (2...power).reduce(base) { result, _ in result * base }
kleines Detail mehr
schnell - Binäre Ausdrücke
quelle
Wenn Sie nicht zur Überlastung des Bedieners neigen (obwohl die
^^
Lösung wahrscheinlich für jemanden klar ist, der Ihren Code liest), können Sie eine schnelle Implementierung durchführen:quelle
mklbtz hat Recht mit der Potenzierung, indem das Quadrieren der Standardalgorithmus für die Berechnung ganzzahliger Potenzen ist, aber die schwanzrekursive Implementierung des Algorithmus scheint etwas verwirrend. Unter http://www.programminglogic.com/fast-exponentiation-algorithms/ finden Sie eine nicht rekursive Implementierung der Exponentiation durch Quadrieren in C. Ich habe versucht, sie hier in Swift zu übersetzen:
Dies könnte natürlich durch Erstellen eines überladenen Operators zum Aufrufen erfunden und neu geschrieben werden, um es allgemeiner zu gestalten, sodass es an allem funktioniert, was das
IntegerType
Protokoll implementiert . Um es generisch zu machen, würde ich wahrscheinlich mit so etwas beginnenAber das wird wahrscheinlich mitgerissen.
quelle
BinaryInteger
.IntegerType
wurde veraltet.Oder nur :
quelle
Kombinieren Sie die Antworten zu einem überladenen Satz von Funktionen (und verwenden Sie "**" anstelle von "^^", wie es einige andere Sprachen verwenden - für mich klarer):
Bei Verwendung von Float können Sie an Präzision verlieren. Wenn Sie numerische Literale und eine Mischung aus Ganzzahlen und Nicht-Ganzzahlen verwenden, erhalten Sie standardmäßig Double. Ich persönlich mag die Möglichkeit, aus stilistischen / lesbaren Gründen einen mathematischen Ausdruck anstelle einer Funktion wie pow (a, b) zu verwenden, aber das bin nur ich.
Alle Operatoren, die bewirken würden, dass pow () einen Fehler auslöst, führen auch dazu, dass diese Funktionen einen Fehler auslösen. Die Last der Fehlerprüfung liegt also weiterhin beim Code, der die Power-Funktion verwendet. KUSS, IMHO.
Die Verwendung der nativen pow () -Funktion ermöglicht es beispielsweise, Quadratwurzeln (2 ** 0,5) oder inverse (2 ** -3 = 1/8) zu ziehen. Aufgrund der Möglichkeit, inverse oder gebrochene Exponenten zu verwenden, habe ich meinen gesamten Code geschrieben, um den Standard-Double-Typ der pow () -Funktion zurückzugeben, der die höchste Genauigkeit zurückgeben sollte (wenn ich mich richtig an die Dokumentation erinnere). Bei Bedarf kann dies auf Int oder Float oder was auch immer typisiert werden, möglicherweise mit Genauigkeitsverlust.
quelle
Es stellt sich heraus, dass Sie auch verwenden können
pow()
. Sie können beispielsweise Folgendes verwenden, um 10 bis 9 auszudrücken.Zusammen mit
pow
,powf()
gibt einfloat
anstelle einesdouble
. Ich habe dies nur auf Swift 4 und macOS 10.13 getestet.quelle
Zum Berechnen verwenden Sie
power(2, n)
einfach:quelle
Swift 4.x Version
quelle
In Swift 5:
Verwenden Sie so
Vielen Dank an die Antwort von @Paul Buis.
quelle
Eine Int-basierte pow-Funktion, die den Wert direkt über die Bitverschiebung für Basis 2 in Swift 5 berechnet:
(Stellen Sie sicher, dass das Ergebnis im Bereich von Int liegt - dies prüft nicht, ob der Fall außerhalb der Grenzen liegt.)
quelle
Beim Versuch, die Überladung zu kombinieren, habe ich versucht, Generika zu verwenden, aber es konnte nicht funktionieren. Ich dachte schließlich, ich würde NSNumber verwenden, anstatt zu versuchen, Generika zu überladen oder zu verwenden. Dies vereinfacht sich zu Folgendem:
Der folgende Code ist dieselbe Funktion wie oben, implementiert jedoch die Fehlerprüfung, um festzustellen, ob die Parameter erfolgreich in Doubles konvertiert werden können.
quelle
Array (Wiederholung: a, Anzahl: b) .reduce (1, *)
quelle
Die anderen Antworten sind großartig, aber wenn Sie es vorziehen, können Sie dies auch mit einer
Int
Erweiterung tun, solange der Exponent positiv ist.quelle
Swift 5
Ich war überrascht, aber ich habe hier keine richtige Lösung gefunden.
Das ist meins:
Beispiel:
quelle
Mir gefällt das besser
quelle
Beispiel:
quelle