Operador de exponenciación en Swift


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

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.


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

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)
}

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


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
}


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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.