Comment obtenir la Puissance d'un Entier dans Swift langue?

j'apprends swift récemment, mais j'ai un problème de base qui ne trouve pas de réponse

je veux quelque chose comme

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

mais la fonction pow ne peut fonctionner qu'avec le nombre double, elle ne fonctionne pas avec le nombre entier, et je ne peux même pas lancer l'int pour doubler par quelque chose comme le Double(A) ou un.double ()...

pourquoi il ne fournit pas la puissance d'entier? il retournera certainement un entier sans ambiguïté ! et Pourquoi je ne peux pas lancer un entier sur un double? il suffit de changer 3 à 3.0 (ou 3.00000... quoi que ce soit)

si j'ai deux entiers et que je veux faire l'opération de puissance, Comment puis-je le faire en douceur?

Merci!

63
demandé sur 林鼎棋 2014-06-13 06:13:14

15 réponses

si vous voulez, vous pouvez déclarer un infix operator pour le faire.

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

j'ai utilisé deux carets de sorte que vous pouvez toujours utiliser le opérateur XOR .

mise à jour pour Swift 3

dans Swift 3, le "numéro magique " precedence est remplacé par 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
62
répondu Grimxn 2016-09-20 08:04:42

à part le fait que vos déclarations de variables comportent des erreurs de syntaxe, cela fonctionne exactement comme vous vous y attendiez. Tout ce que vous avez à faire est de lancer pour doubler, et passer les valeurs à pow. Ensuite, si vous travaillez avec 2 internes, et vous voulez Un Int de l'autre côté de l'opération, il suffit de Cas Retour à Int

import Darwin 

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

let x: Int = Int(pow(Double(a),Double(b)))
34
répondu Mick MacCallum 2016-09-22 22:13:35

il arrive Qu'un Int soit moulé en Double , ce qui n'est pas une solution viable. À certaines grandeurs il y a une perte de précision dans cette conversion. Par exemple, le code suivant ne renvoie pas ce que vous attendez. (Swift 3.0)

Double(Int.max - 1) < Double(Int.max) // false!

Si vous avez besoin d' de précision à haute grandeurs et n'ont pas besoin de s'inquiéter à propos de les exposants négatifs - qui ne peut généralement être résolu avec des entiers de toute façon - alors cette implémentation de l'algorithme exponentiation-by-squaring exponentiation-by-squaring est votre meilleur pari. Selon cette réponse ainsi , c'est " la méthode standard pour faire l'exponentiation modulaire pour des nombres énormes en cryptographie asymétrique."

func pow(_ base: Int, _ power: Int) -> Int {
    func expBySq(_ y: Int, _ x: Int, _ n: Int) -> Int {
        precondition(n >= 0)
        if n == 0 {
            return y
        } else if n == 1 {
            return y * x
        } else if n % 2 == 0 {
            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) 
}
6
répondu mklbtz 2017-05-23 11:54:51

petit détail plus

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

swift-Expressions binaires

4
répondu tylyo 2015-04-18 22:36:29

si vous êtes peu enclin à la surcharge de l'opérateur (bien que la solution ^^ soit probablement claire pour quelqu'un qui lit votre code), vous pouvez faire une implémentation rapide:

let pwrInt:(Int,Int)->Int = { a,b in return Int(pow(Double(a),Double(b))) }
pwrInt(3,4) // 81
4
répondu HenryRootTwo 2015-07-08 22:50:25

combiner les réponses dans un ensemble surchargé de fonctions (et en utilisant "* * "au lieu de" ^ ^ "comme d'autres langues utilisent - plus clair pour moi):

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

en utilisant Float, vous pouvez perdre la précision. Si vous utilisez des caractères numériques et un mélange d'entiers et de non-entiers, vous finirez avec Double par défaut. J'aime personnellement la possibilité d'utiliser une expression mathématique au lieu d'une fonction comme pow(a, b) pour des raisons de style/lisibilité, mais ce n'est que moi.

tout opérateur qui provoquerait pow () à lancer une erreur provoquera également ces fonctions à lancer une erreur, de sorte que le fardeau de la vérification d'erreur reste avec le code en utilisant la fonction de puissance de toute façon. BAISER, À MON HUMBLE AVIS.

en utilisant la fonction native pow() permet par exemple de prendre des racines carrées (2 ** 0.5) ou inverses (2 ** -3 = 1/8). En raison de la possibilité d'utiliser des exposants inverses ou fractionnaires, j'ai écrit tout mon code pour retourner le type Double par défaut de la la fonction pow (), qui devrait retourner la plus précise (si je me souviens bien de la documentation). Si nécessaire, cela peut être moulé par type Jusqu'à Int ou Float ou n'importe quoi, éventuellement avec la perte de précision.

2 ** -3  = 0.125
2 ** 0.5 = 1.4142135623731
2 ** 3   = 8
3
répondu ECJB 2015-10-17 15:00:20

mklbtz est correct au sujet de l'exponentiation par la quadrature étant l'algorithme standard pour le calcul des puissances entières, mais la mise en œuvre recursive de l'algorithme semble un peu confus. Voir http://www.programminglogic.com/fast-exponentiation-algorithms/ pour un non-récursive de la mise en œuvre de l'exponentiation par la quadrature en C. j'ai tenté de le traduire à Swift ici:

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
}

bien sûr, cela pourrait être imaginé par créer un opérateur surchargé pour l'appeler et il pourrait être réécrit pour le rendre plus générique de sorte qu'il fonctionne sur tout ce qui met en œuvre le protocole IntegerType . Pour le rendre générique, je commencerais probablement par quelque chose comme

    func expo<T:IntegerType>(_ base: T, _ power: T) -> T {
    var result : T = 1

mais, c'est probablement en train de s'emballer.

3
répondu Paul Buis 2016-12-01 11:20:25

si vous voulez vraiment une implémentation 'Int only' et que vous ne voulez pas forcer à/à partir de Double , vous aurez besoin de l'implémenter. Voici une implémentation triviale; il y a des algorithmes plus rapides mais cela fonctionnera:

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

dans une vraie implémentation, vous voudriez probablement une vérification d'erreur.

2
répondu GoZoner 2017-02-06 18:48:23

il s'avère que vous pouvez aussi utiliser pow() . Par exemple, vous pouvez utiliser ce qui suit pour exprimer 10 à la 9ème.

pow(10, 9)

avec pow , powf() retourne un float au lieu d'un double . Je ne l'ai testé que sur Swift 4 et macOS 10.13.

2
répondu Jake3231 2018-02-14 23:38:29

ou juste:

var a:Int = 3
var b:Int = 3
println(pow(Double(a),Double(b)))
1
répondu Fafa 2015-05-31 18:46:37

en essayant de combiner la surcharge, j'ai essayé d'utiliser des génériques mais je n'ai pas pu le faire fonctionner. J'ai finalement pensé à utiliser NSNumber au lieu d'essayer de surcharger ou d'utiliser des génériques. Cela simplifie ce qui suit:

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

le code suivant est la même fonction que ci-dessus mais implémente la vérification des erreurs pour voir si les paramètres peuvent être convertis en Doubles avec succès.

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
    }
}
0
répondu ECJB 2015-10-22 04:59:45

pour calculer power(2, n) , il suffit d'utiliser:

let result = 2 << (n-1)
0
répondu Le Binh 2017-10-06 02:06:27

Swift 4.X version

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
}
0
répondu Mahendra GP 2018-05-12 04:22:50

j'aime mieux

func ^ (left:NSNumber, right: NSNumber) -> NSNumber {
    return pow(left.doubleValue,right.doubleValue)
}
var a:NSNumber = 3
var b:NSNumber = 3 
println( a^b ) // 27
-1
répondu Cody Crank 2015-02-06 02:24:45
    func calc (base:Int, number:Int) -> Int {
    var answer : Int = base
    for _ in 2...number {answer *= base } 
    return answer
    }
    calc (2,2)
-3
répondu artnazar 2014-07-24 14:47:21