Числа хранятся в конечной памяти. Независимо от того, выполняете ли вы арифметику с плавающей запятой c, вам нужен способ кодирования десятичного числа в двоичной памяти. Пока у вас ограниченная память (то есть всегда в реальном мире), вы должны выбрать, потратить свои биты на высокий диапазон или высокую точность, или на какой-то компромисс между ними.
7 цифр вводят вас в первую «область» компромисса Float
. Вы можете «сделать это», но есть компромисс: при такой большой величине вы теряете некоторую точность. В данном случае целые числа округляются до ближайшего 10.
Float
- это число с плавающим указателем одинарной точности IEEE 754. Его первая зона «компромисса» находится на уровне 16,777,217
. От 0
до 16,777,216
можно точно представить каждое целое число. После этого не хватит точности, чтобы указать число до 2^0
(единицы, иначе единицы). Следующее, что лучше всего - это представить его правильно вплоть до ближайших 2^1
(двоек).
Проверьте это:
import Foundation
for originalInt in 16_777_210 ... 16_777_227 {
let interMediateFloat = Float(originalInt)
let backAsInt = Int(interMediateFloat)
print("\(originalInt) -> \(backAsInt)")
}
print("\n...\n")
for originalInt in 33_554_430 ... 33_554_443 {
let interMediateFloat = Float(originalInt)
let backAsInt = Int(interMediateFloat)
print("\(originalInt) -> \(backAsInt)")
}
печатает:
16777210 -> 16777210
16777211 -> 16777211
16777212 -> 16777212
16777213 -> 16777213
16777214 -> 16777214
16777215 -> 16777215
16777216 -> 16777216 // Last precisely representable whole number
16777217 -> 16777216 // rounds down
16777218 -> 16777218 // starts skipping by 2s
16777219 -> 16777220
16777220 -> 16777220
16777221 -> 16777220
16777222 -> 16777222
16777223 -> 16777224
16777224 -> 16777224
16777225 -> 16777224
16777226 -> 16777226
16777227 -> 16777228
...
33554430 -> 33554430
33554431 -> 33554432
33554432 -> 33554432
33554433 -> 33554432
33554434 -> 33554432 // Last whole number representable to the closest "two"
33554435 -> 33554436 // rounds up
33554436 -> 33554436
33554437 -> 33554436 // starts skipping by 4s
33554438 -> 33554440
33554439 -> 33554440
33554440 -> 33554440
33554441 -> 33554440
33554442 -> 33554440
33554443 -> 33554444
И так далее. По мере того, как величина становится больше, целые числа представляются со все меньшей и меньшей точностью. В крайнем случае, наибольшее целочисленное значение (340,282,346,638,528,859,811,704,183,484,516,925,440
) и второе наибольшее целочисленное значение (340,282,326,356,119,256,160,033,759,537,265,639,424
) отличаются на 20,282,409,603,651,670,423,947,251,286,016
(2^104
).
Возможность express такого высокие числа происходят именно за счет неспособности точно хранить многие числа около этой величины. Округление происходит. В качестве альтернативы, двоичные целые числа, такие как Swift Int
, имеют идеальную точность для целых чисел (всегда сохраняются с точностью до правильных единиц / единиц), но платят за это значительно меньшим максимальным размером (только 2,147,483,647
для подписанного Int32
).