2016-07-24 17 views
1

FloatまたはDoubleをSwiftのIntに変換する信頼できる方法を見つけようとしています。私は、オーバーフローが発生したときに問題にぶつかります。 SwiftのFloatingから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ビットアーキテクチャでは異なるはずです。

別の方法がありますか?私が見逃していたか、より良い、移植可能な方法でこれを行うには、failableイニシャライザのように?

+0

。 Appleにバグレポートを提出していただければ幸いです。私たちがInt演算のためにオーバーフロー演算子を持つ方法は変ですが、この状況では致命的なエラーになります。迅速な数値はひどく、これはひどいことの一部です... – matt

答えて

2

あなたはDoubleのために、独自のfailable初期化子を作成することにより、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

また、NaNと無限大でこれが期待どおりに機能するかどうかはわかりません。 – deadbeef

+0

NaNと無限大の答えが更新されました。 – vacawama

関連する問題