Exponentiationsoperator in Swift


Antworten:


96

Es gibt keinen Operator, aber Sie können die pow-Funktion folgendermaßen verwenden:

return pow(num, power)

Wenn Sie möchten, können Sie auch einen Operator veranlassen, die pow-Funktion wie folgt aufzurufen:

infix operator ** { associativity left precedence 170 }

func ** (num: Double, power: Double) -> Double{
    return pow(num, power)
}

2.0**2.0 //4.0

Besser zu verwenden **, damit Sie es für Ints verwenden können und nicht mit XOR in Konflikt stehen.
Kevin

3
Der Operator ^ wird in Swift als XOR definiert.
Kostiantyn Koval

21
Warnung! Hier gibt es ein Problem. Zum Beispiel normalerweise in Programmiersprachen -2.0**2.0 = -(2.0**2.0) = -4.0. Dies ist jedoch -2.0**2.0 = (-2.0)**2.0 = 4.0möglicherweise nicht die beabsichtigte Verwendung und kann zu einem ziemlich bösen und schwer auffindbaren Fehler führen.
Daniel Farrell

NSHipster verwendet eine ähnliche Beschreibung, jedoch mit einer Priorität von 160, um mit <<und übereinzustimmen >>. Unterschiedliche Prioritäten führen zu unterschiedlichen Code-Interpretationen. Daher ist es wichtig, eine Priorität für gemeinsame Operatoren festzulegen. Ich weiß nicht, was der beste Standard ist, aber Geben << 2und ** 2der gleiche Vorrang machen Sinn. nshipster.com/swift-operators
Omegaman

8
Ist Potenzierung nicht richtig assoziativ? en.wikipedia.org/wiki/Operator_associativity
vwvan

28

Wenn Sie zufällig 2 auf eine bestimmte Leistung erhöhen, können Sie den bitweisen Linksverschiebungsoperator verwenden:

let x = 2 << 0    // 2
let y = 2 << 1    // 4
let z = 2 << 7    // 256

Beachten Sie, dass der Wert 'power' 1 weniger ist, als Sie vielleicht denken.

Beachten Sie, dass dies schneller ist als pow(2.0, 8.0)und Sie vermeiden müssen, Doppel zu verwenden.


2
Das ist soweit schön, beantwortet aber die Frage nicht wirklich.
Chris

1
Ich war an Zweierpotenzen interessiert, also antwortete es mir.
dldnh

@chanceoperation Alternativ können Sie für 2 hoch n 1 oder 0b00000001 um n Stellen nach links verschieben. Swift Advanced Operators let x = 0b00000001 << exponent // 2**exponent let x = 1 << 0 // 1 let x = 1 << 2 // 4 let x = 1 << 8 // 256
Beepscore

13

Für alle, die nach einer Swift 3-Version des **Infix-Operators suchen :

precedencegroup ExponentiationPrecedence {
  associativity: right
  higherThan: MultiplicationPrecedence
}

infix operator ** : ExponentiationPrecedence

func ** (_ base: Double, _ exp: Double) -> Double {
  return pow(base, exp)
}

func ** (_ base: Float, _ exp: Float) -> Float {
  return pow(base, exp)
}

2.0 ** 3.0 ** 2.0    // 512
(2.0 ** 3.0) ** 2.0  // 64

5
Nett. Vergessen Sie nicht import Darwinzu bekommenpow
iainH

4
Ziemlich sicher, dass die Assoziativität links und nicht rechts sein sollte. 2 ^ 3 ^ 2 ist 64, nicht 512.
Brandonscript

Nun, sowohl in Python als auch in JavaScript 2**3**2ist 512, nicht 64. Ich kenne keine Programmiersprache mit einem linksassoziativen Exponentiationsoperator. Sie sind alle richtig assoziativ. Wenn Sie dies in Swift implementieren, sollten Sie es auf jeden Fall richtig assoziativ tun, um mit anderen gängigen Sprachen sowie mit mathematischen Konventionen konsistent zu sein .
Ray Toal

5

Ich habe es so gemacht:

operator infix ** { associativity left precedence 200 }

func ** (base: Double, power: Double) -> Double {
    return exp(log(base) * power)
}

das scheint ... ineffizient
sam-w

4

Swift 4.2

import Foundation

var n = 2.0 // decimal
var result = 5 * pow(n, 2)
print(result)
// 20.0


2

Wenn Sie sich speziell für den Exponentiationsoperator für IntTyp interessieren , denke ich nicht, dass vorhandene Antworten aufgrund der Art und Weise, wie Gleitkommazahlen im Speicher dargestellt werden, für große Zahlen besonders gut funktionieren würden. Wenn zu konvertieren Floatoder Doubleaus Intund dann wieder zurück (die durch erforderlich ist pow, powfund powlFunktionen in DarwinModul) können Sie Präzision verlieren . Hier ist eine genaue Version für Int:

let pow = { Array(repeating: $0, count: $1).reduce(1, *) }

Beachten Sie, dass diese Version nicht besonders speichereffizient ist und für die Quellcodegröße optimiert ist.

Eine andere Version, die kein Zwischenarray erstellt:

func pow(_ x: Int, _ y: Int) -> Int {
  var result = 1
  for i in 0..<y {
    result *= x
  }
  return result
}


0

Eine alternative Antwort ist die Verwendung von NSExpression

let mathExpression = NSExpression(format:"2.5**2.5")
let answer = mathExpression.expressionValue(with: nil, context: nil) as? Double

oder

let mathExpression = NSExpression(format:"2**3")
let answer = mathExpression.expressionValue(with: nil, context: nil) as? Int
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.