Я только что заметил, что Swift выполняет литье некоторых типов по Int и Double. Когда я пытаюсь оценитьStrange Swift numbers type casting
(10/3.0) - (10/3)
0.333...
ожидается, но на самом деле это 0.0
. Не могли бы вы объяснить это?
Я только что заметил, что Swift выполняет литье некоторых типов по Int и Double. Когда я пытаюсь оценитьStrange Swift numbers type casting
(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
.)
Теперь это может быть неожиданно для всех нас с (объективно-) 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
10 может рассматриваться как деление двух целых чисел здесь.
Это действительно выглядит немного странно, если мы суммируем эти результаты:
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
является деление двух целых констант, как описано выше.
Отличное объяснение! –