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!
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
à 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)))
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)
}
petit détail plus
infix operator ^^ { associativity left precedence 160 }
func ^^ (radix: Int, power: Int) -> Int {
return Int(pow(CGFloat(radix), CGFloat(power)))
}
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
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
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.
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.
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.
ou juste:
var a:Int = 3
var b:Int = 3
println(pow(Double(a),Double(b)))
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
}
}
pour calculer power(2, n)
, il suffit d'utiliser:
let result = 2 << (n-1)
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
}
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
func calc (base:Int, number:Int) -> Int {
var answer : Int = base
for _ in 2...number {answer *= base }
return answer
}
calc (2,2)