Как преобразование «.35» в float
, так и преобразование «.35» в double
дают значение, отличное от .35, поскольку в форматах с плавающей запятой используется двоичная база, поэтому точное математическое значение должно быть аппроксимируется с использованием степеней двух (в данном случае отрицательных степеней двух).
Поскольку формат float
использует меньше битов, его результат менее точен и, в этом случае, менее точен. Значение float
равно 0,3499999940395355224609375, а значение double
равно 0,34999999999999997779553950749686919152736663818359375.
Я не полностью знаком со Swift, но подозреваю, что алгоритм, который он использует для преобразования CGFloat
в десятичную (с параметрами по умолчанию), выглядит примерно так:
- Создает фиксированное количество десятичных цифр с правильным округлением от фактического значения
CGFloat
до количества цифр, а затем подавляет любые завершающие нули. Например, если точное математическое значение равно 0,34999999999999997… и форматирование использует 15 значащих цифр, промежуточный результат будет «0,350000000000000», а затем он будет закорочен до «0,35».
Способ работы с float
и double
:
- При преобразовании в
double
, .35 становится 0,34999999999999997779553950749686919152736663818359375. При печати с использованием вышеуказанных методов результат будет «0,35».
- При преобразовании в
float
, .35 становится 0,3499999940395355224609375. При печати с использованием вышеуказанного метода, результат «0.349999994039536».
Таким образом, значения float
и double
отличаются от .35, но форматирование для печати не использует достаточно цифр, чтобы показать отклонение для значения double
, в то время как оно использует достаточно цифр, чтобы показать отклонение для значения float
.