2014-06-13 16 views
54

我迅速的學習最近,但我無法找到答案如何在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 ...無論如何)

如果我有兩個整數,我想做功率操作,我該怎麼做順利?

謝謝!

+0

這些類型的聲明是錯誤的 –

+0

TYOR的SORRY,我修正了它 –

+0

由於[這個原因]大多數語言沒有整數冪函數(https://stackoverflow.com/q/2398442/995714) –

回答

50

如果你願意,你可以聲明一個infixoperator來做到這一點。

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

更新斯威夫特3

在斯威夫特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 
+0

所以如果你想爲Floats做這個,你可以這樣做:中綴操作符^^ {} func ^^(基數:浮點數,次數:浮點數) - >浮點數{ return Float(pow(Double(radix),Double(power))) } – padapa

+0

func ^^ (radix:Double,power:Double) - > Double {double(pow(Double(radix),Double(power))} – padapa

+3

}我發現這並沒有像我預期的那樣表現得很好,因爲優先級已關閉。對於指數運算符,請將優先級設置爲160(請參見https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html#//apple_ref/doc/uid/TP40014097-CH32-ID383和https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html)就像這樣:'infix operator ^^ {precedence 160} func ^^'...等等 –

34

除了你的變量聲明有語法錯誤之外,它的工作原理正如你所期望的那樣。您只需將其轉換爲Double,並將值傳遞給pow。然後,如果你有2個整數工作,你想一個Int回到了操作的另一邊,只是案發回INT

import Darwin 

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

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

如果你真的想要一個「詮釋只是」實施和唐我不想強制/從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 

在你可能會想一些錯誤檢查真正落實。

+0

This是一個完全有效的答案。在某些情況下,將Ints轉換爲雙精度會失去精度,所以對於Int pow來說這不是一個可行的解決方案。試試在Swift 3 REPL中運行'Double(Int.max - 1) mklbtz

+2

要縮短它,你可以通過'reduce'調用來實現。 'return(2 ... power).reduce(base){result,_ in result * base}' – mklbtz

+1

也許你可以通過使用UInt去掉前提條件 – hashemi

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

這是一個很好的做法,可以解釋爲什麼你的代碼提供了一個解決方案,而不是將代碼轉儲到答案中。 –

+1

這遠不是一個正確的功能函數。什麼是0作爲指數或任何負值。 – macbirdie

-1

我喜歡這個更好

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

這取代了標準的xor操作符。使用這將使你的代碼以一種非常意想不到的方式對任何不知道你重寫單克拉的人行事。 – wjl

4

小詳細信息更多

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

swift - Binary Expressions

1

或者只是:

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

如果你對運算符重載(雖然^^解決方案可能是清楚的人讀你的代碼),你可以做一個快速的實現不願意:

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

將答案組合成一組超載的函數nctions(以及使用「**」而不是「^^」一些其他的語言使用 - 更清晰的給我):

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

當使用浮動,你可能會失去精度。如果使用數字文字以及整數和非整數的組合,默認情況下最終會使用Double。我個人喜歡使用數學表達式而不是像pow(a,b)這樣的功能來實現文體/可讀性的功能,但這只是我自己。

任何會導致pow()拋出錯誤的操作符也會導致這些函數拋出一個錯誤,所以錯誤檢查的負擔仍然在於使用power函數的代碼。 KISS,恕我直言。使用本地pow()函數允許例如取平方根(2 ** 0.5)或反(2 ** -3 = 1/8)。由於可能使用反向或小數指數,我寫了所有的代碼來返回pow()函數的默認Double類型,它應該返回最高精度(如果我正確記住文檔)。如果需要的話,可以將其輸入到Int或Float或其他類型,可能會導致精度下降。

2 ** -3 = 0.125 
2 ** 0.5 = 1.4142135623731 
2 ** 3 = 8 
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))} 

以下代碼是相同的功能,但以上實施錯誤檢查,看看是否可以將參數成功地轉換爲雙打。

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

有時候,鑄造IntDouble是不是一個可行的解決方案。在某種程度上,這種轉換會降低精度。例如,下面的代碼不會返回您可能直觀地預期的內容。 (Swift 3。0)

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

如果您需要在高幅度精度,無需擔心負指數 - 這通常可以解決與整數反正沒有 - 那麼這個實施tail-recursive exponentiation-by-squaring algorithm的是你的最好的選擇。根據this SO answer,這是「在非對稱密碼學中對大數進行模冪運算的標準方法。」

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) 
} 
+0

當然,您可以隨時將其定義爲運算符(如更常用的答案所示)或「Int」的擴展,或者您可以將這些東西稱爲此自由函數 - 無論您的心是否渴望。 – mklbtz

2

mklbtz是有關被平方計算的整數次冪的標準算法冪正確的,但該算法的尾遞歸的實現似乎有點混亂。由C.平方見http://www.programminglogic.com/fast-exponentiation-algorithms/的非遞歸實現冪的我已經嘗試在這裏翻譯成斯威夫特:

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

要計算power(2, n),只需使用:

let result = 2 << (n-1) 
0

原來你也可以使用pow()。例如,您可以使用以下表達10到9。

pow(10, 9) 

隨着powpowf()返回float而不是double。我只在Swift 4和macOS 10.13上測試過。