Exponentiation operator in Swift
Asked Answered
S

10

104

I don't see an exponentiation operator defined in the base arithmetic operators in the Swift language reference.

Is there really no predefined integer or float exponentiation operator in the language?

Salicin answered 5/6, 2014 at 16:46 Comment(1)
In my case, this worked as the solution: https://mcmap.net/q/211630/-swift-39-s-pow-function-won-39-t-accept-doubles-as-argumentsKrissy
T
115

There isn't an operator but you can use the pow function like this:

return pow(num, power)

If you want to, you could also make an operator call the pow function like this:

infix operator ** { associativity left precedence 170 }

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

2.0**2.0 //4.0
Theophrastus answered 5/6, 2014 at 16:57 Comment(7)
Better to use **, so you can use it on ints and not conflict with XOR.Menken
^ operator is define as XOR in Swift.Sol
Warning! There is a problem here. For example, usually in programming languages, -2.0**2.0 = -(2.0**2.0) = -4.0. However, here -2.0**2.0 = (-2.0)**2.0 = 4.0, which might not be the intended use and could causes quite a nasty and hard to track down bug.Arlinearlington
NSHipster uses a similar description but with a precedence of 160 to match << and >>. Different precedences will lead to different code interpretations, so standardizing on a precedence for common operators is important. I don't know what the best standard is, but giving << 2 and ** 2 the same precedence makes some sense. nshipster.com/swift-operatorsCalciferol
Isn't exponentiation right associative? en.wikipedia.org/wiki/Operator_associativityRailroader
In more recent Swift versions, the first line should be: infix operator ** : BitwiseShiftPrecedenceFrumentaceous
what's the 170 about?Paleo
P
38

If you happen to be raising 2 to some power, you can use the bitwise left shift operator:

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

Notice that the 'power' value is 1 less than you might think.

Note that this is faster than pow(2.0, 8.0) and lets you avoid having to use doubles.

Petigny answered 22/2, 2015 at 23:16 Comment(4)
This is nice as far as it goes, but doesn't really answer the question.Engraft
I was interested in powers of two, so it answered it for me.Nourishment
@Petigny Alternatively, for 2 to the power of n you can shift 1 or 0b00000001 to the left by n places Swift Advanced Operators let x = 0b00000001 << exponent // 2**exponent let x = 1 << 0 // 1 let x = 1 << 2 // 4 let x = 1 << 8 // 256Enwreathe
You should be doing 1 << exponent, because you’re literally moving the bit left on a small endian value. 1 << 1 == 2, or imagine 00000001 gets the bit shifted left 1, giving 00000010, which is 2 in binary. I like this solution though. I incorporated it into my comprehensive answer below.Neper
F
14

For anyone looking for a Swift 3 version of the ** infix operator:

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
Fadeout answered 11/1, 2017 at 2:19 Comment(3)
Nice. Don't forget to import Darwin to get powSandusky
Pretty sure the associativity should be left, not right. 2^3^2 is 64, not 512.Terrence
Well, in both Python and JavaScript 2**3**2 is 512, not 64. I don't know any programming language with a left-associative exponentiation operator. They're all right-associative. If you implement this in Swift, you should definitely do it right-associative to be consistent with other popular languages, as well as mathematical convention.Fried
M
7

Swift 4.2

import Foundation

var n = 2.0 // decimal
var result = 5 * pow(n, 2)
print(result)
// 20.0
Midmost answered 1/3, 2019 at 23:5 Comment(0)
I
5

I did it like so:

operator infix ** { associativity left precedence 200 }

func ** (base: Double, power: Double) -> Double {
    return exp(log(base) * power)
}
Imperialism answered 24/6, 2014 at 20:22 Comment(1)
this seems... inefficientBough
L
3

There isn't one but you have the pow function.

Lombardo answered 5/6, 2014 at 16:54 Comment(0)
S
1

Like most of the C-family of languages, there isn't one.

Stroller answered 5/6, 2014 at 16:52 Comment(0)
P
1

If you're specifically interested in the exponentiation operator for Int type, I don't think that existing answers would work particularly well for large numbers due to the way how floating point numbers are represented in memory. When converting to Float or Double from Int and then back (which is required by pow, powf and powl functions in Darwin module) you may lose precision. Here's a precise version for Int:

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

Note that this version isn't particularly memory efficient and is optimized for source code size.

Another version that won't create an intermediate array:

func pow(_ x: Int, _ y: Int) -> Int {
  var result = 1
  for i in 0..<y {
    result *= x
  }
  return result
}
Parsonage answered 17/11, 2018 at 12:17 Comment(2)
This function fails to pass test cases. What’s the correct behavior for exponents that are negative? It seems this pow function would round them all up to 1, which might be acceptable until the base is also negative, e.g. -1**-1 = -1, -10**-1 = -0.1.Neper
The correct behavior for negative powers is probably to match what you’d get from casting the pow(Double, Double) result as an Int. I’ve provided a new answer with that solution, but also optimizing for speed by handling boundary cases and using the bitwise left shift operator for powers of 2 and -2.Neper
G
1

An alternative answer is to use NSExpression

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

or

let mathExpression = NSExpression(format:"2**3")
let answer = mathExpression.expressionValue(with: nil, context: nil) as? Int
Gigot answered 3/1, 2019 at 15:46 Comment(0)
N
1

This answer provides a tested and optimized* function for calculating integer powers of integers, while also providing several versions of the custom ** operators for exponentiation.

* At least I think it’s optimized, based on what I read on this page.

My guess is that Swift deliberately does not provide this because of the need to choose what to do about results that have absolute values of less than 1. Do you want it to round to 0 or implicitly cast to a decimal type? The compiler can’t know, and choosing a default may lead to people using it without realizing what mathematical choice they just made.

In Swift 5.3:

import Foundation

precedencegroup ExponeniationPrecedence {
    associativity: right  // This makes Towers of Powers work correctly
    higherThan: MultiplicationPrecedence
}

infix operator ** : ExponeniationPrecedence

public func **(_ base: Int, _ exponent: Int) -> Int {
    return pow(base, exponent)
}
public func **(_ base: Double, _ exponent: Double) -> Double {
    return pow(base, exponent)
}
public func **(_ base: Decimal, _ exponent: Int) -> Decimal {
    return pow(base, exponent)
}
public func **(_ base: Float, _ exponent: Float) -> Float {
    return powf(base, exponent)
}

/// Calculate exponentiation of integer base and integer exponent, returning integer result.
/// 
/// Exponentiation that would result in absolute values of less than 1 (i.e. exponent is negative and base is not 1 or -1) are rounded 0.
public func pow(_ base: Int, _ exponent: Int) -> Int {
    // Optimize cases for certain exponents
    switch exponent {
    case 0:
        return 1 
    case 1:
        return base
    case _ where exponent < 0 && base != -1 && base != 1:
        // Negative exponents of integers always round to zero, except if the base is 1 or -1
        return 0
    default:
        break 
    }
    
    // Optimize cases for certain bases
    switch base {
    case -1:
        if exponent % 2 == 0 {
            return -1 * base
        } else {
            return base
        }
    case 0, 1:
        return base 
    case -2, 2:
        // Use the bitwise left shift operator to efficiently calculate powers of 2 and -2
        let result = 1 << exponent
        if base == -2 && exponent % 2 == 1 {
            return -1 * result
        }
        return result
    default:
        var result = 1
        for i in 1 ... exponent {
            result *= base
        }
        return result
    }
}

/// Calculate powers of integer base and integer exponent using Foundation's pow function by casting both the base and the exponent as Doubles, calling pow, but without casting the result.
/// Useful if rounding results between -1 and 1 to zero is not acceptable. 
public func pow(_ base: Int, _ exponent: Int) -> Double {
    return pow(Double(base), Double(exponent))
}

/// Calculate powers of integer base and integer exponent using Foundation's pow function by casting both the base and the exponent as Doubles, calling pow, and then casting the result as an Int
/// If results are -1<x<1, round to 0.
public func castPow(_ base: Int, _ exponent: Int) -> Int {
    return Int(pow(base, exponent))
}

Test cases for the pow(Int, Int) function:


// Test Exponent = 0
assert(0**0 == 1)
assert(1**0 == 1)
assert(2**0 == 1)

// Test Exponent = 1
assert(-1**1 == -1)
assert(0**1 == 0)
assert(1**1 == 1)
assert(2**1 == 2)

// Test Exponent = -1
assert(-1 ** -1 == -1)
assert(0 ** -1 == 0)
assert(1 ** -1 == 1)
assert(2 ** -1 == 0)

// Test Exponent = 2
assert(-1 ** 2 == 1)
assert(0 ** 2 == 0)
assert(1 ** 2 == 1)
assert(2 ** 2 == 4)
assert(3 ** 2 == 9)

// Test Base = 0
assert(0**0 == 1)
assert(0**1 == 0)
assert(0**2 == 0)

// Test Base = 1
assert(1 ** -1 == 1)
assert(1**0 == 1)
assert(1**1 == 1)
assert(1**2 == 1)

// Test Base = -1
assert(-1 ** -1 == -1)
assert(-1**0 == 1)
assert(-1**1 == -1)
assert(-1**2 == 1)
assert(-1**2 == 1)
assert(-1**3 == -1)

// Test Base = 2
assert(2 ** -1 == 0)
assert(2**0 == 1)
assert(2**1 == 2)
assert(2**2 == 4)
assert(2**3 == 8)

// Test Base = -2
assert(-2 ** -1 == 0)
assert(-2**0 == 1)
assert(-2**1 == -2)
assert(-2**2 == 4)
assert(-2**3 == -8)

// Test Base = 3
assert(3 ** -1 == 0)
assert(3**0 == 1)
assert(3**1 == 3)
assert(3**2 == 9)
assert(3**3 == 27)

// Test Towers of Powers
assert(2**2**2 == 16)
assert(3**2**2 == 81)
assert(2**2**3 == 256)
assert(2**3**2 == 512)
Neper answered 27/11, 2021 at 20:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.