Как получить Силу некоторого целого в языке Swift?
В последнее время я изучаю быстро, но у меня есть основная проблема, которая не может найти ответ
Я хочу получить что-то вроде
var a:Int = 3
var b:Int = 3
println( pow(a,b) ) // 27
но функция pow может работать только с двойным номером, она не работает с целым числом, и я даже не могу заставить int удваивать что-то вроде Double (a) или a.double()...
Почему он не обеспечивает мощность целого? он обязательно вернет целое число без двусмысленности!
и почему я не могу отличить целое число до двойника? он просто меняет 3 на 3.0 (или 3.00000... что угодно)
Если я получил два целых числа, и я хочу сделать операцию с питанием, как я могу сделать это плавно?
Спасибо!
Ответы
Ответ 1
Если вам нравится, вы можете объявить infix
operator
, чтобы сделать это.
// Put this at file level anywhere in your project
infix operator ^^ { associativity left precedence 160 }
func ^^ (radix: Int, power: Int) -> Int {
return Int(pow(Double(radix), Double(power)))
}
// ...
// Then you can do this...
let i = 2 ^^ 3
// ... or
println("2³ = \(2 ^^ 3)") // Prints 2³ = 8
Я использовал двух кареток, чтобы вы все еще могли использовать оператор XOR.
Обновление для Swift 3
В Swift 3 "магическое число" precedence
заменяется на precedencegroups
:
precedencegroup PowerPrecedence { higherThan: MultiplicationPrecedence }
infix operator ^^ : PowerPrecedence
func ^^ (radix: Int, power: Int) -> Int {
return Int(pow(Double(radix), Double(power)))
}
// ...
// Then you can do this...
let i2 = 2 ^^ 3
// ... or
print("2³ = \(2 ^^ 3)") // Prints 2³ = 8
Ответ 2
Кроме того, что ваши объявления переменных имеют синтаксические ошибки, это работает именно так, как вы ожидали. Все, что вам нужно сделать, это привести a
и b
к Double и передать значения в pow
. Затем, если вы работаете с 2 Ints и хотите вернуть Int на другую сторону операции, просто приведите обратно к Int.
import Darwin
let a: Int = 3
let b: Int = 3
let x: Int = Int(pow(Double(a),Double(b)))
Ответ 3
Иногда приведение Int
к Double
не является жизнеспособным решением. В некоторых величинах при этом преобразовании теряется точность. Например, следующий код не возвращает то, что вы могли бы интуитивно ожидать.
Double(Int.max - 1) < Double(Int.max) // false!
Если вам нужна точность при больших значениях и вам не нужно беспокоиться об отрицательных показателях - которые в общем случае не могут быть решены с помощью целых чисел - тогда эта реализация алгоритма хвостовой рекурсивной возведения в квадрат - ваш лучший выбор. Согласно этому ответу SO, это "стандартный метод для модульного возведения в степень для огромных чисел в асимметричной криптографии".
// using Swift 5.0
func pow<T: BinaryInteger>(_ base: T, _ power: T) -> T {
func expBySq(_ y: T, _ x: T, _ n: T) -> T {
precondition(n >= 0)
if n == 0 {
return y
} else if n == 1 {
return y * x
} else if n.isMultiple(of: 2) {
return expBySq(y, x * x, n / 2)
} else { // n is odd
return expBySq(y * x, x * x, (n - 1) / 2)
}
}
return expBySq(1, base, power)
}
Примечание: в этом примере я использовал универсальный T: BinaryInteger
. Это так, что вы можете использовать Int
или UInt
или любой другой целочисленный тип.
Ответ 4
Если вы действительно хотите реализовать только "Int only" и не хотите принуждать к/от Double
, вам нужно ее реализовать. Вот тривиальная реализация; есть более быстрые алгоритмы, но это будет работать:
func pow (base:Int, power:UInt) -> Int {
var answer : Int = 1
for _ in 0..power { answer *= base }
return answer
}
> pow (2, 4)
$R3: Int = 16
> pow (2, 8)
$R4: Int = 256
> pow (3,3)
$R5: Int = 27
В реальной реализации вы, вероятно, захотите проверить некоторые ошибки.
Ответ 5
немного подробнее подробнее
infix operator ^^ { associativity left precedence 160 }
func ^^ (radix: Int, power: Int) -> Int {
return Int(pow(CGFloat(radix), CGFloat(power)))
}
swift - Двоичные выражения
Ответ 6
Если вы не склонны к перегрузке оператора (хотя решение ^^
, вероятно, ясно для кого-то, читающего ваш код), вы можете сделать быструю реализацию:
let pwrInt:(Int,Int)->Int = { a,b in return Int(pow(Double(a),Double(b))) }
pwrInt(3,4) // 81
Ответ 7
mklbtz корректно относится к экспоненциации путем возведения в квадрат стандартного алгоритма вычисления целых степеней, но хвосто-рекурсивная реализация алгоритма кажется немного запутанной. См. http://www.programminglogic.com/fast-exponentiation-algorithms/ для нерекурсивной реализации возведения в степень возведения в квадрат в C. Я попытался перевести его в Swift здесь:
func expo(_ base: Int, _ power: Int) -> Int {
var result = 1
while (power != 0){
if (power%2 == 1){
result *= base
}
power /= 2
base *= base
}
return result
}
Конечно, это может быть связано с созданием перегруженного оператора для его вызова, и его можно переписать, чтобы сделать его более универсальным, чтобы он работал на все, что реализовало протокол IntegerType
. Чтобы сделать его общим, я, вероятно, начинал бы с чего-то вроде
func expo<T:IntegerType>(_ base: T, _ power: T) -> T {
var result : T = 1
Но это, вероятно, увлекается.
Ответ 8
Объединение ответов в перегруженный набор функций (и использование "**" вместо "^^", как некоторые другие языки используют - яснее для меня):
// http://stackoverflow.com/questions/24196689/how-to-get-the-power-of-some-integer-in-swift-language
// Put this at file level anywhere in your project
infix operator ** { associativity left precedence 160 }
func ** (radix: Double, power: Double) -> Double { return pow(radix, power) }
func ** (radix: Int, power: Int ) -> Double { return pow(Double(radix), Double(power)) }
func ** (radix: Float, power: Float ) -> Double { return pow(Double(radix), Double(power)) }
При использовании Float вы можете потерять точность. Если вы используете числовые литералы и сочетание целых чисел и нецелых чисел, вы по умолчанию получите Double. Мне лично нравится возможность использовать математическое выражение вместо функции типа pow (a, b) для стилистических/удобочитаемости, но это только я.
Любые операторы, которые вызовут ошибку pow(), также вызовут эти функции, чтобы вызвать ошибку, поэтому бремя проверки ошибок по-прежнему остается в коде с использованием функции мощности. KISS, IMHO.
Использование функции native pow() позволяет, например, принимать квадратные корни (2 ** 0,5) или инверсные (2 ** -3 = 1/8). Из-за возможности использовать обратные или дробные показатели я написал весь свой код, чтобы вернуть двойной тип функции pow() по умолчанию, который должен вернуть максимальную точность (если я правильно помню документацию). Если это необходимо, это может быть сбрасывается с помощью типа Int или Float или что-то еще, возможно, с потерей точности.
2 ** -3 = 0.125
2 ** 0.5 = 1.4142135623731
2 ** 3 = 8
Ответ 9
Оказывается, вы также можете использовать pow()
. Например, вы можете использовать следующее, чтобы выразить от 10 до 9.
pow(10, 9)
Наряду с pow
, powf()
возвращает число с float
вместо double
. Я проверял это только на Swift 4 и macOS 10.13.
Ответ 10
Или просто:
var a:Int = 3
var b:Int = 3
println(pow(Double(a),Double(b)))
Ответ 11
Чтобы вычислить power(2, n)
, просто используйте:
let result = 2 << (n-1)
Ответ 12
Версия Swift 4.x
precedencegroup ExponentiationPrecedence {
associativity: right
higherThan: MultiplicationPrecedence
}
infix operator ^^: ExponentiationPrecedence
public func ^^ (radix: Float, power: Float) -> Float {
return pow((radix), (power))
}
public func ^^ (radix: Double, power: Double) -> Double {
return pow((radix), (power))
}
public func ^^ (radix: Int, power: Int) -> Int {
return NSDecimalNumber(decimal: pow(Decimal(radix), power)).intValue
}
Ответ 13
В Swift 5:
extension Int{
func expo(_ power: Int) -> Int {
var result = 1
var powerNum = power
var tempExpo = self
while (powerNum != 0){
if (powerNum%2 == 1){
result *= tempExpo
}
powerNum /= 2
tempExpo *= tempExpo
}
return result
}
}
Используйте как это
2.expo(5) // pow(2, 5)
Благодаря ответу Пола Буиса.
Ответ 14
Пытаясь объединить перегрузку, я попытался использовать дженерики, но не смог заставить ее работать. Я, наконец, решил использовать NSNumber вместо того, чтобы пытаться перегружать или использовать generics. Это упрощает следующее:
typealias Dbl = Double // Shorter form
infix operator ** {associativity left precedence 160}
func ** (lhs: NSNumber, rhs: NSNumber) -> Dbl {return pow(Dbl(lhs), Dbl(rhs))}
Следующий код представляет собой ту же функцию, что и выше, но реализует проверку ошибок, чтобы проверить, могут ли параметры быть преобразованы в парные числа успешно.
func ** (lhs: NSNumber, rhs: NSNumber) -> Dbl {
// Added (probably unnecessary) check that the numbers converted to Doubles
if (Dbl(lhs) ?? Dbl.NaN) != Dbl.NaN && (Dbl(rhs) ?? Dbl.NaN) != Dbl.NaN {
return pow(Dbl(lhs), Dbl(rhs))
} else {
return Double.NaN
}
}
Ответ 15
добавлять
extension Int {
func pow(_ lhr: Int, _ rhr: Int) -> Int {
return Int(Foundation.pow(Double(lhr), Double(rhr)))
}
}
и вы можете использовать свой код
var a:Int = 3
var b:Int = 3
println( pow(a,b) ) // 27
Ответ 16
Мне нравится это лучше
func ^ (left:NSNumber, right: NSNumber) -> NSNumber {
return pow(left.doubleValue,right.doubleValue)
}
var a:NSNumber = 3
var b:NSNumber = 3
println( a^b ) // 27
Ответ 17
func calc (base:Int, number:Int) -> Int {
var answer : Int = base
for _ in 2...number {answer *= base }
return answer
}
Пример:
calc (2,2)