Я только что заметил, что Swift выполняет литье некоторых типов по Int и Double. Когда я пытаюсь оценить
(10 / 3.0) - (10 / 3)
0.333...
, но на самом деле 0.0
.
Может кто-нибудь объяснить это, пожалуйста?
Я только что заметил, что Swift выполняет литье некоторых типов по Int и Double. Когда я пытаюсь оценить
(10 / 3.0) - (10 / 3)
0.333...
, но на самом деле 0.0
.
Может кто-нибудь объяснить это, пожалуйста?
Да, я также нашел это довольно неожиданным. Double
соответствует как FloatLiteralConvertible
, так и IntegerLiteralConvertible
(ExpressibleByFloatLiteral
и ExpressibleByIntegerLiteral
в Swift 3). Поэтому
Double
может быть инициализирован литералом с плавающей запятой
let a = 3.0
или с целым литералом:
let b : Double = 10
(То же самое верно для других типов с плавающей запятой, таких как Float
и
CGFloat
.)
Теперь это может быть неожиданно для всех нас с фоном (Objective-) C что оба утверждения
let x : Double = 10/4 // x = 2.5 . Really? Yes!
let y = 10/4 as Double // Same here ...
присвойте переменной 0.25
переменной. Из контекста результат
деление должно быть Double
, а Swift не подразумевает конвертирование типов.
Поэтому /
должен быть оператором деления с плавающей запятой
func /(lhs: Double, rhs: Double) -> Double
поэтому компилятор создает оба аргумента как Double
из литералов
"10" и "4". (Если 10/4
рассматривались как деление двух целых чисел
то результат также будет целым числом, и это не может быть назначено
до Double
.)
Обратите внимание, что это отличается от
let z = Double(10/4) // z = 2.0 . (I just thought that I understood it &%$!?)
который выполняет целочисленное деление и преобразует результат в Double
.
Double
имеет конструктор init(_ v: Int)
, поэтому 10/4
можно рассматривать как деление двух целых чисел.
Это выглядит немного странно, если мы суммируем эти результаты:
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
Теперь мы можем применить эти результаты к вашему выражению
(10 / 3.0) - (10 / 3)
Первая часть (10 / 3.0)
может быть только Double
, поэтому -
должен быть оператором вычитания с плавающей запятой
func -(lhs: Double, rhs: Double) -> Double
и, следовательно, (10 / 3)
также должен быть Double
. Опять же, /
должен быть оператором деления с плавающей запятой, поэтому 10
и 3
рассматриваются как константы Double
.
Поэтому выражение эквивалентно
(Double(10) / 3.0) - (Double(10) / Double(3))
и оценивается до 0.0
. Если вы измените выражение на
(10 / 3.0) - Double(10 / 3)
то результат 0.333...
, потому что в этом контексте 10 / 3
является разделение двух целых констант, как объяснялось выше.