В дополнение к тому, что было сказано в других ответах, например, модули Intel с плавающей запятой используют внутренне полное 80-битное представление с плавающей запятой с превышением числа битов ... так, когда оно округляет число до ближайшего 23-битное float
число (как я предполагаю из вашего вывода) думает, что оно может быть очень точным и учитывает все биты в int
.
IEEE-752 определяет 32-битное число с плавающей точкой в качестве числа с 23 битами, выделенными для хранения значения и, что означает, что для нормализованного числа, в котором неявный старший бит является неявным (не хранится, поскольку это всегда 1
бит), у вас фактически есть 24 бита значения и в форме 1xxxxxxx_xxxxxxxx_xxxxxxxx
, что означает число 2^24-1
- последнее, что вы сможете точно представить (на самом деле 11111111_11111111_11111111
). После этого вы можете представлять все четные числа, но не шансы, так как вам не хватает младшего значащего бита для их представления. Это должно означать, что вы можете представить:
v decimal dot.
16777210 == 2^24-6 11111111_11111111_11111010.
16777211 == 2^24-5 11111111_11111111_11111011.
16777212 == 2^24-4 11111111_11111111_11111100.
16777213 == 2^24-3 11111111_11111111_11111101.
16777214 == 2^24-2 11111111_11111111_11111110.
16777215 == 2^24-1 11111111_11111111_11111111.
16777216 == 2^24 10000000_00000000_00000000_. <-- here the leap becomes 2 as there are no more than 23 bits to play with.
16777217 == 2^24+1 10000000_00000000_00000000_. (there should be a 1 bit after the last 0)
16777218 == 2^24+2 10000000_00000000_00000001_.
...
33554430 == 2^25-2 11111111_11111111_11111111_.
33554432 == 2^26 10000000_00000000_00000000__. <-- here the leap becomes 4 as there's another shift
33554436 == 2^26+4 10000000_00000000_00000001__.
...
Если вы представляете проблему в базе 10, предположим, что у нас есть числа с плавающей запятой всего 3 десятичных знака в значении и показатель степени 10, чтобы поднять силу , Когда мы начинаем считать с 0
, мы получаем:
1 => 1.00E0
...
8 => 8.00E0
9 => 9.00E0
10 => 1.00E1 <<< see what happened here... this is the same number as the first but with the ten's exponent incremented, meaning a one digit shift of every digit to the left.
11 => 1.10E1
...
98 => 9.80E1
99 => 9.90E1
100 => 1.00E2 <<< and here.
101 => 1.01E2
...
996 => 9.96E2
997 => 9.97E2
998 => 9.98E2
999 => 9.99E2
1000 => 1.00E3 <<< exact, but here you don't have anymore a fourth digit to represent units.
1001 => 1.00E3 (this number cannot be represented exactly)
...
1004 => 1.00E3 (this number cannot be represented exactly)
1005 => 1.01E3 (this number cannot be represented exactly) <<< here rounding is applied, but the implementation is free to do whatever it wants.
...
1009 => 1.01E3 (this number cannot be represented exactly)
1010 => 1.01E3 <<< this is the next number that can be represent exactly with three floating point digits. So we switched from an increment of one by one to an increment of ten by ten.
...
Примечание
Показанный вами случай - это один из режимов округления, указанных для процессоров Intel, он округляется до четное число ближе, но в случае, если оно составляет половину расстояния, оно подсчитывает число в один бит в значении и округляет в большую сторону, когда оно нечетное, и округляется в меньшую сторону, когда оно четное (это позволяет избежать округления всегда так важно иногда банковские операции --- банки никогда не используют числа с плавающей запятой, потому что они не имеют точного контроля округления)