[integer] Swift 언어로 Integer의 힘을 얻는 방법은 무엇입니까?

최근 빠르게 배우고 있는데 답을 찾을 수없는 기본적인 문제가 있습니다

나는 같은 것을 얻고 싶다.

var a:Int = 3
var b:Int = 3
println( pow(a,b) ) // 27

그러나 pow 함수는 이중 숫자로만 작동 할 수 있으며 정수로는 작동하지 않으며 Double (a) 또는 a.double ()과 같은 것으로 int를 이중으로 캐스팅 할 수도 없습니다.

정수의 거듭 제곱을 제공하지 않는 이유는 무엇입니까? 명확하게 모호하지 않은 정수를 반환합니다! 왜 정수를 double로 캐스트 할 수 없습니까? 3을 3.0 (또는 3.00000 … 무엇이든)으로 변경합니다.

정수가 두 개 있고 전원 연산을하고 싶다면 어떻게하면 원활하게 할 수 있습니까?

감사!



답변

원하는 경우를 선언 할 수 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에서 “magic number” 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


답변

변수 선언에 구문 오류가 있다는 것 외에는 예상대로 정확히 작동합니다. 당신이해야 할 일은 캐스트 abDouble로 값을 전달하는 것 pow입니다. 그런 다음 2 개의 Int로 작업하고 작업의 다른쪽에 Int를 다시 사용하려면 Int로 다시 캐스팅하십시오.

import Darwin

let a: Int = 3
let b: Int = 3

let x: Int = Int(pow(Double(a),Double(b)))


답변

때때로, 캐스팅 IntA를하는 것은 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또는 다른 정수와 유사한 유형을 사용할 수 있도록하기위한 것 입니다.


답변

정말로 ‘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

실제 구현에서는 오류 검사를 원할 것입니다.


답변

조금 더 자세히

   infix operator ^^ { associativity left precedence 160 }
   func ^^ (radix: Int, power: Int) -> Int {
       return Int(pow(CGFloat(radix), CGFloat(power)))
   }

swift-이진 표현식


답변

연산자 오버로딩 ^^이 마음에 들지 않는다면 ( 솔루션은 코드를 읽는 사람에게 분명 할 수 있지만) 빠른 구현을 수행 할 수 있습니다.

let pwrInt:(Int,Int)->Int = { a,b in return Int(pow(Double(a),Double(b))) }
pwrInt(3,4) // 81


답변

mklbtz는 제곱이 정수 거듭 제곱을 계산하는 표준 알고리즘 인 지수화에 대해 정확하지만 알고리즘의 꼬리 재귀 구현은 약간 혼란스러워 보입니다. C로 제곱하여 지수를 비재 귀적으로 구현하려면 http://www.programminglogic.com/fast-exponentiation-algorithms/ 를 참조 하십시오 . 여기에서 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

그러나 그것은 아마도 사라질 것입니다.