Swift言語で整数の力を得る方法は?


102

私は最近素早く学習していますが、答えが見つからないという基本的な問題があります

私は何かを得たいです

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

しかし、pow関数は倍精度数でのみ機能し、整数では機能しません。また、Double(a)やa.double()などの方法でintをdoubleにキャストすることもできません...

なぜそれは整数の力を供給しないのですか?それは間違いなく曖昧さのない整数を返します!なぜ整数をdoubleにキャストできないのですか?3を3.0に変更します(または3.00000 ...何でも)

2つの整数を取得して電源操作を実行したい場合、どうすればスムーズに実行できますか?

ありがとう!


これらの型宣言は間違っています
Edgar Aroutiounian


1
@phuclvのメモは、このトピックに関するすばらしい議論を示しています。リンクのテキストを「これらの理由」に変更します
eharo2

回答:


78

必要に応じて、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演算子を引き続き使用できるように、2つのキャレットを使用しました。

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

したがって、フロートに対してこれを行う場合は、次のようにします。中置演算子^^ {} func ^^(基数:Float、power:Float)-> Float {return Float(pow(Double(radix)、Double(power )))}
padapa 2015

func ^^(radix:Double、power:Double)-> Double {return Double(pow(Double(radix)、Double(power)))}
padapa

3
優先順位がオフになっているため、これが期待どおりに動作しないことがわかりました。指数演算子の場合は、次のように優先度を160に設定します(developer.apple.com/library/ios/documentation/Swift/Conceptual/…およびdeveloper.apple.com/library/ios/documentation/Swift/Conceptual/…を参照)。infix operator ^^ { precedence 160 } func ^^...など
Tim Camber、2015年

私はこのソリューションが本当に好きですが、Swift 3では機能しません。それを機能させる方法はありますか?
Vanya 2016

1
func p(_ b: Bool) -> Double { return b?-1:1 }
Grimxn 2016

59

変数宣言に構文エラーがあることを除いて、これは期待どおりに機能します。あなたがしなければならないのは、キャストabてDoubleに値を渡し、値をに渡すことだけですpow。次に、2つのIntを使用していて、操作の反対側でIntを戻したい場合は、Intにキャストバックします。

import Darwin 

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

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

この答えは、Double型とInt型で最も明確です。
midtownguru

それが私が欲しいものです、ありがとう。Pythonでは、ちょうど3 ** 3。時々、Swiftを使用してアルゴリズムの問​​題を解決する必要があります。Pythonを使用する場合と比較すると、それは本当に苦痛です。
ChuckZHB

13

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。これによりIntUIntまたはその他の整数のような型を使用できます。


そしてもちろん、これを演算子(より一般的な答えが示唆するように)または拡張としていつでも定義することができます。あるいは、Intこれらのことをこの自由関数と呼ぶことができます。
mklbtz 2017

どうやら、このソリューションはスタックオーバーフローの例外につながる
Vyacheslav

11

「Intのみ」の実装が本当に必要で、/への強制を望まない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

実際の実装では、おそらくいくつかのエラーチェックが必要になります。


これは完全に有効な答えです。IntをDoubleに変換すると精度が失われる場合があるため、これはInt powの実行可能なソリューションではありません。Double(Int.max - 1) < Double(Int.max)Swift 3 REPLで実行してみてください。驚かれるかもしれません。
mklbtz 2016

2
短くするために、これをreduce呼び出しで実装できます。return (2...power).reduce(base) { result, _ in result * base }
mklbtz 2016

1
おそらく、UIntをパワーにすることで前提条件を取り除くことができます
hashemi

4

少し詳細

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

swift-バイナリ式


4

演算子のオーバーロードに気が進まない場合(^^ソリューションがコードを読んでいる人にはおそらく明らかであるとしても)、すばやく実装できます。

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

4

mklbtzは、整数の累乗を計算するための標準アルゴリズムである2乗により、べき乗について正しいですが、アルゴリズムの末尾再帰実装は少し混乱しているようです。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

しかし、それはおそらく夢中になっています。


1
非常に素晴らしい!Swift> 4.0(Xcode 9.0)でこれを一般的に行うには、を使用しますBinaryIntegerIntegerType廃止されました。
mklbtz

3

あるいは単に :

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

3

回答を多重定義された関数のセットに結合します(他の言語が使用する「^^」の代わりに「**」を使用します-私にはより明確です):

// 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()にエラーをスローさせるすべての演算子は、これらの関数にもエラーをスローさせるため、エラーチェックの負担は、とにかくpower関数を使用するコードにあります。キス、私見。

ネイティブのpow()関数を使用すると、たとえば平方根(2 ** 0.5)または逆数(2 ** -3 = 1/8)を取ることができます。逆指数または分数指数を使用する可能性があるため、すべてのコードを記述して、pow()関数のデフォルトのDouble型を返します。必要に応じて、これはIntやFloatなどの型キャストにキャストできますが、精度が失われる可能性があります。

2 ** -3  = 0.125
2 ** 0.5 = 1.4142135623731
2 ** 3   = 8

pow()は、小数部も非常に重要である大規模な計算には適していません。私にとってあなたの答えはヒントを与えます。ありがとう:)
マヘンドラ

3

あなたも使えることがわかりましたpow()。たとえば、次のように使用すると、10から9を表現できます。

pow(10, 9)

返しの代わりに。私はこれをSwift 4とmacOS 10.13でのみテストしました。powpowf()floatdouble


1
pow(a、b)は、b <0の場合、NaNを返します。これのテストを追加できます:let power =(b> = 0)?pow(a、b):1 / pow(a、-b); aはDecimalとして宣言する必要があることに注意してください。let a:Decimal = 2; レットb = -3
claude31 '12年

2

を計算するにはpower(2, n)、次を使用します。

let result = 2 << (n-1)

1

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
}

1

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)

@Paul Buisの回答に感謝します。



1

Swift 5のベース2のビットシフトを介して値を直接計算するIntベースのpow関数:

func pow(base: Int, power: UInt) -> Int {
    if power == 0 { return 1 }
    // for base 2, use a bit shift to compute the value directly
    if base == 2 { return 2 << Int(power - 1) }
    // otherwise multiply base repeatedly to compute the value
    return repeatElement(base, count: Int(power)).reduce(1, *)
}

(結果がIntの範囲内であることを確認してください-これは範囲外のケースをチェックしません)


1

他の答えは素晴らしいですが、望ましい場合Intは、指数が正である限り、内線でそれを行うこともできます。

extension Int {   
    func pow(toPower: Int) -> Int {
        guard toPower > 0 else { return 0 }
        return Array(repeating: self, count: toPower).reduce(1, *)
    }
}

2.pow(toPower: 8) // returns 256

0

オーバーロードを組み合わせようとして、ジェネリックスを使用しようとしましたが、機能しませんでした。ようやく、ジェネリックをオーバーロードしたり使用したりする代わりに、NSNumberを使用することを考えました。これにより、次のことが簡単になります。

typealias Dbl = Double // Shorter form
infix operator ** {associativity left precedence 160}
func ** (lhs: NSNumber, rhs: NSNumber) -> Dbl {return pow(Dbl(lhs), Dbl(rhs))}

次のコードは上記と同じ関数ですが、エラーチェックを実装して、パラメーターをDoubleに正常に変換できるかどうかを確認しています。

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

-1

スウィフト5

驚いたが、ここでは適切な正しい解決策が見つからなかった。

これは私のものです:

enum CustomMath<T: BinaryInteger> {

    static func pow(_ base: T, _ power: T) -> T {
        var tempBase = base
        var tempPower = power
        var result: T = 1

        while (power != 0) {
            if (power % 2 == 1) {
                result *= base
            }
            tempPower = tempPower >> 1
            tempBase *= tempBase
        }
        return result
    }
}

例:

CustomMath.pow(1,1)

-2

私はこれが好きです

func ^ (left:NSNumber, right: NSNumber) -> NSNumber {
    return pow(left.doubleValue,right.doubleValue)
}
var a:NSNumber = 3
var b:NSNumber = 3 
println( a^b ) // 27

3
これは、標準のxor演算子を置き換えます。これを使用すると、単一のカラットをオーバーライドしていることを知らない人にとって、コードが非常に予期しない方法で動作します。
wjl 2015年

-3
func calc (base:Int, number:Int) -> Int {
    var answer : Int = base
    for _ in 2...number {answer *= base } 
    return answer
}

例:

calc (2,2)

1
単にコードを解答にダンプするのではなく、コードがソリューションを提供する理由を説明することは良い習慣です。
Rudi Kershaw 2014

1
そして、それは正しいべき関数からはほど遠いです。指数または負の値としての0はどうでしょう。
Macbirdie 2014年

また、「calc」という名前は、そのような特定の演算で使用するには一般的すぎます。cal(2,2)は、2つの数値に適用したいあらゆる計算を意味します... * 2、2 / 2、2pow2、2root2など
eharo2
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.