Strani numeri Swift di tipo casting

Ho appena notato che Swift fa un po ‘di casting su Int e Double. Quando provo a valutare

(10 / 3.0) - (10 / 3) 

0.333... è previsto, ma in realtà è 0.0 . Qualcuno potrebbe spiegarlo per favore?

Sì, ho anche trovato questo abbastanza sorprendente. Double conforms sia a FloatLiteralConvertible che a IntegerLiteralConvertible ( ExpressibleByFloatLiteral e ExpressibleByIntegerLiteral in Swift 3). Pertanto un Double può essere inizializzato con letterale floating point

 let a = 3.0 

o con un intero letterale :

 let b : Double = 10 

(Lo stesso vale per altri tipi di virgola mobile come Float e CGFloat .)

Ora potrebbe essere inaspettato per tutti noi con uno sfondo (objective) C che entrambe le dichiarazioni

 let x : Double = 10/4 // x = 2.5 . Really? Yes! let y = 10/4 as Double // Same here ... 

assegnare il valore 0.25 alla variabile. Dal contesto, il risultato della divisione deve essere un Double e Swift non converte implicitamente i tipi. Pertanto / deve essere l’operatore di divisione in virgola mobile

 func /(lhs: Double, rhs: Double) -> Double 

quindi il compilatore crea entrambi gli argomenti come Double s dai letterali “10” e “4”. (Se 10/4 sono stati trattati come la divisione di due interi, il risultato sarebbe anche un numero intero e non può essere assegnato a un Double ).

Si noti che questo è diverso da

 let z = Double(10/4) // z = 2.0 . (I just thought that I understood it &%$!?) 

che fa una divisione intera e converte il risultato in Double . Double ha un init(_ v: Int) costruttore, e quindi 10/4 può essere trattato come la divisione di due interi qui.

Sembra davvero un po ‘strano se riassumiamo questi risultati:

 let x : Double = 10/4 // x = 2.5 let y = 10/4 as Double // y = 2.5 let z = Double(10/4) // z = 2.0 

Ora possiamo applicare questi risultati alla tua espressione

 (10 / 3.0) - (10 / 3) 

La prima parte (10 / 3.0) può essere solo una Double , quindi deve essere l’operatore di sottrazione in virgola mobile

 func -(lhs: Double, rhs: Double) -> Double 

e quindi (10 / 3) deve anche essere una Double . Di nuovo, / deve essere l’operatore di divisione in virgola mobile, quindi 10 e 3 sono considerati come costanti Double .

Quindi l’espressione è equivalente a

 (Double(10) / 3.0) - (Double(10) / Double(3)) 

e valuta a 0.0 . Se si modifica l’espressione in

 (10 / 3.0) - Double(10 / 3) 

quindi il risultato è 0.333... perché in questo contesto, 10 / 3 è la divisione di due costanti intere, come spiegato sopra.