Що це працює зовсім не банально! Це властивість представлення IEEE з плаваючою точкою, що int∘floor = ⌊⋅⌋, якщо величина розглянутих чисел невелика, але можливі різні подання там, де int (floor (2.3)) може бути 1.
У цій публікації пояснюється, чому вона працює в такому діапазоні .
У подвоєнні ви можете без проблем представляти 32-бітні цілі числа. Не може бути жодних питань округлення. Точніше, парні можуть представляти всі цілі числа між і включати 2 53 та -2 53 .
Коротке пояснення : подвійний може зберігати до 53 двійкових цифр. Коли вам потрібно більше, число праворуч забито нулями.
Звідси випливає, що 53 з них - найбільше число, яке можна зберігати без прокладки. Природно, усі (цілі) числа, що потребують менших цифр, можуть бути точно збережені.
Додавання до 111 (пропущеного) 111 (53) дає 100 ... 000, (53 нулі). Як ми знаємо, ми можемо зберігати 53 цифри, що робить найбільш правильним нульове набивання.
Звідси походить 2 53 .
Більш детально: нам потрібно розглянути, як працює плаваюча точка IEEE-754.
1 bit 11 / 8 52 / 23 # bits double/single precision
[ sign | exponent | mantissa ]
Потім кількість обчислюється наступним чином (виключаючи особливі випадки, які тут не мають значення):
-1 знак × 1.mantissa × 2 показник - зміщення
де зміщення = 2 показник - 1 - 1 , тобто 1023 та 127 для подвійної / одиничної точності відповідно.
Знаючи, що множення на 2 X просто зміщує всі біти X місць вліво, легко помітити, що будь-яке ціле число повинно мати всі біти в мантісі, які закінчуються справа від десяткової крапки до нуля.
Будь-яке ціле число, крім нуля, має таку форму у двійковій формі:
1x ... x де x -es представляють біти праворуч від MSB (найбільш значущий біт).
Оскільки ми виключили нуль, завжди буде MSB, який є одним - ось чому він не зберігається. Щоб зберегти ціле число, ми повинні привести його до вищезгаданої форми: -1 знак × 1.mantissa × 2 показник - зміщення .
Це говорить так само, як переміщення бітів через десяткову точку, поки не залишиться лише MSB вліво від MSB. Усі біти праворуч від десяткової крапки потім зберігаються в мантісі.
З цього ми бачимо, що ми можемо зберігати не більше 52 двійкових цифр крім MSB.
Звідси випливає, що найбільше число, де явно зберігаються всі біти
111(omitted)111. that's 53 ones (52 + implicit 1) in the case of doubles.
Для цього нам потрібно встановити показник, таким чином, щоб десяткова точка змістилася на 52 місця. Якби ми збільшили показник на одиницю, ми не можемо знати цифру праворуч ліворуч після десяткової крапки.
111(omitted)111x.
За умовою, це 0. Установивши всю мантісу на нуль, ми отримаємо таке число:
100(omitted)00x. = 100(omitted)000.
Це 1, за яким 53 нулі, 52 збережені та 1 додано через показник.
Він представляє 2 53 , який позначає межу (як негативну, так і позитивну), між якою ми можемо точно представити всі цілі числа. Якби ми хотіли додати один до 2 53 , нам доведеться встановити неявний нуль (позначений символом x
) на один, але це неможливо.
math.floor
повертає float в v2.6 , але він повертає ціле число в v3 . На даний момент (майже шість років після закінчення програми) ця проблема може з'являтися рідко.