2016-07-24 58 views
1

我試圖找到一種可靠的方法將Swift中的FloatDouble轉換爲Int。當發生溢出時,我會遇到問題。在Swift中Failable Float到Int轉換

讓我們來看看下面的例子:

let double = 9223372036854775807.0 // This is 2^63 - 1 (aka Int.max on 64 bits architecture) 

print("Int.max is   : \(Int.max)") 
print(String(format: "double value is : %f", double)) 
print(String(format: "Double(Int.max) is : %f", Double(Int.max))) 

let int: Int 
if (double >= Double(Int.max)) { 
    print("Warning : double is too big for int !") 
    int = Int.max 
} else { 
    int = Int(double) 
} 

它打印:

Int.max is   : 9223372036854775807 
double value is : 9223372036854775808.000000 
Double(Int.max) is : 9223372036854775808.000000 
Warning : double is too big for int ! 

這種做法是非常麻煩的。另外,您可能注意到我測試的是double >= Double(Int.max)而不是double > Double(Int.max)。這是因爲Double(Int.max)實際上等於Int.max + 1,因爲四捨五入。而且我的代碼對於32位體系結構可能應該不同。

那麼還有其他方法嗎?就像我會錯過的一個可分解的初始化程序,或者一個更好,便攜的方法來做到這一點?

+0

我只是對這個問題的另一個線程評論。我希望你能向蘋果提交一份錯誤報告。我們如何爲Int算術計算溢出運算符是很奇怪的,但在這種情況下我們得到的只是一個致命的錯誤。 Swift數字是可怕的,這只是可怕的一部分... – matt

回答

2

您可以通過創建自己的failable初始化爲Double延長Int

extension Int { 
    init?(double: Double) { 
     if double >= Double(Int.max) || double < Double(Int.min) || double.isNaN || double.isInfinite { 
      return nil 
     } else { 
      self = Int(double) 
     } 
    } 
} 

if let i = Int(double: 17) { 
    print(i) 
} else { 
    print("nil") 
} 

// It also handles NaN and Infinite 
let nan = sqrt(-1.0) 
let inf = 1e1000 

Int(double: nan) // nil 
Int(double: inf) // nil 
+0

謝謝。我希望內置的東西能夠被編譯器優化,但我想現在沒有這種東西(我也沒有看到Swift 3中的任何東西......)。 – deadbeef

+0

此外,我不確定這將如NaNs和無限一樣按預期工作。 – deadbeef

+0

NaN and infinity已更新答案。 – vacawama