Подтвердить что ты не робот

Как получить Силу некоторого целого в языке 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... что угодно)

Если я получил два целых числа, и я хочу сделать операцию с питанием, как я могу сделать это плавно?

Спасибо!

4b9b3361

Ответ 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)