Operator potęgowania w języku Swift

81

Nie widzę operatora potęgowania zdefiniowanego w podstawowych operatorach arytmetycznych w odwołaniu do języka Swift.

Czy naprawdę nie ma w języku predefiniowanych liczb całkowitych lub zmiennoprzecinkowych?

mcgregor94086
źródło
W moim przypadku, to pracował jako rozwiązanie: stackoverflow.com/a/28710112/2161007
Nayyar

Odpowiedzi:

96

Nie ma operatora, ale możesz użyć funkcji pow w następujący sposób:

return pow(num, power)

Jeśli chcesz, możesz również zmusić operatora do wywołania funkcji pow w następujący sposób:

infix operator ** { associativity left precedence 170 }

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

2.0**2.0 //4.0
Connor
źródło
Lepszy w użyciu **, więc możesz go używać na intach i nie powodować konfliktów z XOR.
Kevin,
3
Operator ^ jest zdefiniowany jako XOR w języku Swift.
Kostiantyn Koval
22
Ostrzeżenie! Tu jest problem. Na przykład zwykle w językach programowania -2.0**2.0 = -(2.0**2.0) = -4.0. Jednak tutaj -2.0**2.0 = (-2.0)**2.0 = 4.0, co może nie być przeznaczeniem i może spowodować dość nieprzyjemny i trudny do wyśledzenia błąd.
Daniel Farrell
NSHipster używa podobnego opisu, ale z priorytetem 160, aby dopasować <<i >>. Różne priorytety prowadzą do różnych interpretacji kodu, dlatego ważna jest standaryzacja priorytetów dla wspólnych operatorów. Nie wiem, jaki jest najlepszy standard, ale dawanie << 2i ** 2ten sam priorytet ma sens. nshipster.com/swift-operators
Omegaman
8
Czy potęga nie jest prawidłowa asocjacyjna? en.wikipedia.org/wiki/Operator_associativity
vwvan
28

Jeśli zdarzy ci się podnieść 2 do jakiejś potęgi, możesz użyć bitowego operatora przesunięcia w lewo:

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

Zauważ, że wartość „mocy” jest o 1 mniejsza niż myślisz.

Zauważ, że jest to szybsze niż pow(2.0, 8.0)i pozwala uniknąć konieczności używania podwójnych.

przypadkowa operacja
źródło
2
To jest miłe, ale tak naprawdę nie odpowiada na pytanie.
Chris
1
Interesowały mnie potęgi dwojga, więc odpowiedziała za mnie.
dldnh
@chanceoperation Alternatywnie, dla 2 do potęgi n możesz przesunąć o 1 lub 0b00000001 w lewo o n umieszcza 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

Dla każdego, kto szuka wersji **operatora infix w języku Swift 3 :

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
reitermarkus
źródło
5
Miły. Nie zapomnij import Darwindostaćpow
np.
4
Całkiem pewna, że ​​asocjatywność powinna zostać pozostawiona, a nie właściwa. 2 ^ 3 ^ 2 to 64, a nie 512.
brandonscript
Cóż, zarówno w Pythonie, jak i JavaScript 2**3**2jest 512, a nie 64. Nie znam żadnego języka programowania z lewostronnym operatorem potęgowania. Wszystkie są prawicowe. Jeśli zaimplementujesz to w Swift, zdecydowanie powinieneś zrobić to prawidłowo asocjacyjnie, aby zachować zgodność z innymi popularnymi językami, a także konwencją matematyczną .
Ray Toal
5

Zrobiłem to tak:

operator infix ** { associativity left precedence 200 }

func ** (base: Double, power: Double) -> Double {
    return exp(log(base) * power)
}
ldanilek
źródło
to wydaje się ... nieefektywne
sam-w
4

Swift 4.2

import Foundation

var n = 2.0 // decimal
var result = 5 * pow(n, 2)
print(result)
// 20.0
Edison
źródło
3

Nie ma jednego, ale masz powfunkcję.

Pręt
źródło
2

Jeśli jesteś szczególnie zainteresowany operatorem potęgowania dla Inttypu, nie sądzę, aby istniejące odpowiedzi działały szczególnie dobrze dla dużych liczb ze względu na sposób, w jaki liczby zmiennoprzecinkowe są reprezentowane w pamięci. Podczas konwersji do Floatlub Doublez, Inta następnie z powrotem (co jest wymagane przez pow,powf i powlfunkcje w Darwinmodule) może spowodować utratę precyzji . Oto dokładna wersja Int:

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

Zwróć uwagę, że ta wersja nie jest szczególnie wydajna pod kątem pamięci i jest zoptymalizowana pod kątem rozmiaru kodu źródłowego.

Inna wersja, która nie utworzy tablicy pośredniej:

func pow(_ x: Int, _ y: Int) -> Int {
  var result = 1
  for i in 0..<y {
    result *= x
  }
  return result
}
Max Desiatov
źródło
1

Podobnie jak większość języków z rodziny C, nie ma jednego.

David Berry
źródło
0

Alternatywną odpowiedzią jest użycie NSExpression

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

lub

let mathExpression = NSExpression(format:"2**3")
let answer = mathExpression.expressionValue(with: nil, context: nil) as? Int
Ryan Heitner
źródło