Operador de exponenciación en Swift

81

No veo un operador de exponenciación definido en los operadores aritméticos base en la referencia del lenguaje Swift.

¿Realmente no existe un operador de exponenciación de número entero o flotante predefinido en el idioma?

mcgregor94086
fuente
En mi caso, esto funcionó como la solución: stackoverflow.com/a/28710112/2161007
Nayyar

Respuestas:

96

No hay un operador, pero puede usar la función pow de esta manera:

return pow(num, power)

Si lo desea, también puede hacer que un operador llame a la función pow de esta manera:

infix operator ** { associativity left precedence 170 }

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

2.0**2.0 //4.0
Connor
fuente
Es mejor usarlo **, para que pueda usarlo en ints y no entrar en conflicto con XOR.
Kevin
3
^ operador se define como XOR en Swift.
Kostiantyn Koval
22
¡Advertencia! Aquí hay un problema. Por ejemplo, por lo general en los lenguajes de programación, -2.0**2.0 = -(2.0**2.0) = -4.0. Sin embargo, aquí -2.0**2.0 = (-2.0)**2.0 = 4.0, que podría no ser el uso previsto y podría causar un error bastante desagradable y difícil de rastrear.
Daniel Farrell
NSHipster usa una descripción similar pero con una precedencia de 160 para que coincida con <<y >>. Diferentes precedentes conducirán a diferentes interpretaciones del código, por lo que es importante estandarizar una precedencia para operadores comunes. No sé cuál es el mejor estándar, pero dar << 2y ** 2la misma precedencia tiene algún sentido. nshipster.com/swift-operators
Omegaman
8
¿No es la exponenciación asociativa a la derecha? en.wikipedia.org/wiki/Operator_associativity
vwvan
28

Si aumenta 2 a algo de potencia, puede usar el operador de desplazamiento a la izquierda bit a bit:

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

Observe que el valor de 'potencia' es 1 menos de lo que podría pensar.

Tenga en cuenta que esto es más rápido que pow(2.0, 8.0)y le permite evitar tener que usar dobles.

operación casual
fuente
2
Esto es bueno hasta donde llega, pero realmente no responde a la pregunta.
Chris
1
Estaba interesado en potencias de dos, así que me respondió.
dldnh
@chanceoperation Alternativamente, para 2 a la potencia de n se puede cambiar 1 o 0b00000001 hacia la izquierda n lugares Swift operadores avanzados let x = 0b00000001 << exponent // 2**exponent let x = 1 << 0 // 1 let x = 1 << 2 // 4 let x = 1 << 8 // 256
beepscore
13

Para cualquiera que busque una versión Swift 3 del **operador infijo:

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
fuente
5
Agradable. No te olvides de import Darwinconseguirpow
iainH
4
Estoy bastante seguro de que la asociatividad debería ser a la izquierda, no a la derecha. 2 ^ 3 ^ 2 es 64, no 512.
brandonscript
Bueno, tanto en Python como en JavaScript 2**3**2es 512, no 64. No conozco ningún lenguaje de programación con un operador de exponenciación asociativo a la izquierda. Todos son asociativos a la derecha. Si implementa esto en Swift, definitivamente debería hacerlo correctamente asociativo para ser consistente con otros lenguajes populares, así como con las convenciones matemáticas .
Ray Toal
5

Lo hice así:

operator infix ** { associativity left precedence 200 }

func ** (base: Double, power: Double) -> Double {
    return exp(log(base) * power)
}
ldanilek
fuente
esto parece ... ineficiente
sam-w
4

Rápido 4.2

import Foundation

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

No hay uno, pero tienes la powfunción.

varilla
fuente
2

Si está específicamente interesado en el operador de exponenciación para el Inttipo, no creo que las respuestas existentes funcionen particularmente bien para números grandes debido a la forma en que los números de punto flotante se representan en la memoria. Al convertir hacia Floato Doubledesde Inty luego hacia atrás (que es requerido por pow, powfy powlfunciones en el Darwinmódulo) puede perder precisión . Aquí hay una versión precisa para Int:

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

Tenga en cuenta que esta versión no es particularmente eficiente en memoria y está optimizada para el tamaño del código fuente.

Otra versión que no creará una matriz intermedia:

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

Como la mayoría de los idiomas de la familia C, no hay uno.

David Berry
fuente
0

Una respuesta alternativa es usar NSExpression

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

o

let mathExpression = NSExpression(format:"2**3")
let answer = mathExpression.expressionValue(with: nil, context: nil) as? Int
Ryan Heitner
fuente