У більшості мов програмування числа з плаваючою комою представлені так само, як наукові позначення : з експонентом і мантісою (також називається знаменням). Скажімо 9.2
, дуже просте число - це насправді ця частка:
5179139571476070 * 2 -49
Там, де є показник, -49
і є мантіса 5179139571476070
. Причиною неможливості представити деякі десяткові числа таким чином є те, що і експонент, і мантіса повинні бути цілими числами. Іншими словами, всі плавці повинні бути цілим числом, помноженим на цілу силу 2 .
9.2
може бути просто 92/10
, але 10 не може бути виражено як 2 n, якщо n обмежено цілими значеннями.
Побачення даних
По-перше, кілька функцій, щоб побачити компоненти, які створюють 32- та 64-бітні float
. Замальовуйте їх, якщо ви дбаєте лише про вихід (наприклад, у Python):
def float_to_bin_parts(number, bits=64):
if bits == 32: # single precision
int_pack = 'I'
float_pack = 'f'
exponent_bits = 8
mantissa_bits = 23
exponent_bias = 127
elif bits == 64: # double precision. all python floats are this
int_pack = 'Q'
float_pack = 'd'
exponent_bits = 11
mantissa_bits = 52
exponent_bias = 1023
else:
raise ValueError, 'bits argument must be 32 or 64'
bin_iter = iter(bin(struct.unpack(int_pack, struct.pack(float_pack, number))[0])[2:].rjust(bits, '0'))
return [''.join(islice(bin_iter, x)) for x in (1, exponent_bits, mantissa_bits)]
За цією функцією існує велика кількість складностей, і це було б досить дотично пояснити, але якщо ви зацікавлені, важливим ресурсом для наших цілей є модуль структури .
Python float
- це 64-бітове число з подвоєною точністю. В інших мовах, таких як C, C ++, Java і C #, подвійна точність має окремий тип double
, який часто реалізується у вигляді 64 біт.
Коли ми називаємо цю функцію своїм прикладом 9.2
, ось що ми отримуємо:
>>> float_to_bin_parts(9.2)
['0', '10000000010', '0010011001100110011001100110011001100110011001100110']
Інтерпретація даних
Ви побачите, що я розділив повернене значення на три компоненти. До таких компонентів належать:
- Знак
- Експонент
- Mantissa (також називається Significand, або Фракція)
Знак
Знак зберігається в першому компоненті як єдиний біт. Це легко пояснити: 0
означає, що поплавок - це додатне число; 1
означає, що це негативно. Оскільки 9.2
позитивне, наше знакове значення 0
.
Експонент
Експонент зберігається в середньому компоненті як 11 біт. У нашому випадку 0b10000000010
. У десятковій частині це означає значення 1026
. Вигадка цього компонента полягає в тому, що вам потрібно відняти число, що дорівнює 2 (# біт) - 1 - 1, щоб отримати справжній показник; у нашому випадку це означає віднімання 0b1111111111
(десяткове число 1023
), щоб отримати справжній показник, 0b00000000011
(десяткове число 3).
Мантісса
Мантіса зберігається в третьому компоненті у вигляді 52 біт. Однак є і придумка цього компонента. Щоб зрозуміти цю химерність, врахуйте число в науковій нотації, як це:
6.0221413х10 23
Mantissa була б 6.0221413
. Нагадаємо, що мантіса у наукових позначеннях завжди починається з однієї ненульової цифри. Те ж саме стосується двійкового, за винятком того, що двійковий має лише дві цифри: 0
і 1
. Тож двійкова мантія завжди починається з 1
! Коли поплавок зберігається, 1
фронт двійкової мантіси опускається, щоб заощадити місце; ми повинні розмістити його в передній частині нашого третього елемента, щоб отримати справжню мантісу:
1.0010011001100110011001100110011001100110011001100110
Це передбачає не просто просте доповнення, оскільки біти, що зберігаються в нашому третьому компоненті, насправді являють собою дробову частину мантіси, праворуч від точки радіації .
Маючи справу з десятковими числами, ми «переміщаємо десяткову точку» шляхом множення або ділення на потужності 10. У двійкових ми можемо зробити те саме, множивши або ділимо на потужності на 2. Оскільки наш третій елемент має 52 біт, ми ділимо це на 2 52, щоб перемістити 52 місця праворуч:
0,0010011001100110011001100110011001100110011001100110
У десятковій системі числення, це те ж саме , як поділ 675539944105574
на 4503599627370496
отримати 0.1499999999999999
. (Це один приклад співвідношення, яке можна виразити точно у двійковій формі, але лише приблизно у десятковій формі ; детальніше див.: 675539944105574/4503599627370496 .)
Тепер, коли ми перетворили третій компонент у дробове число, додавання 1
дає справжню мантісу.
Перекомпонування компонентів
- Знак (перший компонент):
0
за позитивний, 1
за негативний
- Експонент (середній компонент): відніміть 2 (# біт) - 1 - 1, щоб отримати справжній показник
- Мантісса (останній компонент): розділіть на 2 (# біт) і додайте,
1
щоб отримати справжню мантісу
Обчислення числа
Збираючи всі три частини разом, ми отримуємо це двійкове число:
1.0010011001100110011001100110011001100110011001100110 x 10 11
Що ми можемо потім перетворити з двійкового в десятковий:
1.1499999999999999 x 2 3 (неточно!)
І множимо, щоб виявити остаточне подання числа, яке ми почали з ( 9.2
) після збереження у вигляді значення з плаваючою комою:
9.1999999999999993
Представляючи себе дробом
9.2
Тепер, коли ми побудували число, можна реконструювати його в простий дріб:
1.0010011001100110011001100110011001100110011001100110 x 10 11
Змініть мантісу на цілу кількість:
10010011001100110011001100110011001100110011001100110 x 10 11-110100
Перетворити в десятковий:
5179139571476070 х 2 3-52
Віднімаємо показник:
5179139571476070 х 2 -49
Перетворіть негативний показник у поділ:
5179139571476070/2 49
Помножимо показник:
5179139571476070/562949953421312
Що дорівнює:
9.1999999999999993
9.5
>>> float_to_bin_parts(9.5)
['0', '10000000010', '0011000000000000000000000000000000000000000000000000']
Вже ви можете бачити мантісу лише 4 цифри, а за ними ціла партія нулів. Але пройдемося кроками.
Зберіть бінарні наукові позначення:
1,0011 x 10 11
Зсуньте десяткову точку:
10011 х 10 11-100
Віднімаємо показник:
10011 х 10 -1
Двійкові до десяткових:
19 х 2 -1
Негативний показник поділу:
19/2 1
Помножимо показник:
19/2
Дорівнює:
9.5
Подальше читання