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?
swift
exponentiation
mcgregor94086
źródło
źródło
Odpowiedzi:
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
źródło
**
, więc możesz go używać na intach i nie powodować konfliktów z XOR.-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.<<
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<< 2
i** 2
ten sam priorytet ma sens. nshipster.com/swift-operatorsJeś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.źródło
let x = 0b00000001 << exponent // 2**exponent let x = 1 << 0 // 1 let x = 1 << 2 // 4 let x = 1 << 8 // 256
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
źródło
import Darwin
dostaćpow
2**3**2
jest 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ą .Zrobiłem to tak:
operator infix ** { associativity left precedence 200 } func ** (base: Double, power: Double) -> Double { return exp(log(base) * power) }
źródło
Swift 4.2
import Foundation var n = 2.0 // decimal var result = 5 * pow(n, 2) print(result) // 20.0
źródło
Nie ma jednego, ale masz
pow
funkcję.źródło
Jeśli jesteś szczególnie zainteresowany operatorem potęgowania dla
Int
typu, 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 doFloat
lubDouble
z,Int
a następnie z powrotem (co jest wymagane przezpow
,powf
ipowl
funkcje wDarwin
module) może spowodować utratę precyzji . Oto dokładna wersjaInt
: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 }
źródło
Podobnie jak większość języków z rodziny C, nie ma jednego.
źródło
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
źródło