Двійкові числа Розуміють l; кодування знаків та коми - Бузут
Ми щодня стикаємося з від’ємними числами та десятковими числами. У двійковій програмі немає знака мінус чи десяткової коми. У цьому випадку, як машина, яка працює лише у двійковому вигляді, справляється з цим ?

Ми також обговоримо поняття точності числа. Тобто розмір, виділений для його зберігання: скільки значущих цифр ми можемо зберегти.
Управління негативами
Як тільки ми говоримо про віднімання, ми розуміємо, що число може бути від’ємним. Тому ми ставимо перед собою питання про збереження числа в двійковому вигляді. Очевидно, що ви повинні перекласти знак у двійкове представлення. Для цього мають бути двійкові числа завжди фіксованого розміру.
Таким чином, для числа, вираженого в одному байті, для вираження знака використовується найбільш значущий біт. 0 - це +, а 1 - -. Тому ми розуміємо, що змінна, закодована в одному байті, може містити від -128 до +127, якщо вона допускає негативи. Якщо вказано, що він не підписаний, значення складають від 0 до 255.
Щоб знайти мінус двійкового числа, просто оберніть усі біти цього числа і додайте один. Додаємо одиницю, оскільки є лише один нуль. Це дозволяє уникнути позитивного нуля і негативного нуля, що призведе до випадку, коли +0 ≠ -0, саме з цієї причини ми можемо підніматися до -128, а не до -127.
Отже 0111 0100 - це додатне число (116dec). Двійкове представлення його від'ємного значення становить 1000 1100, тобто всі біти перевернуті, плюс один: 1000 1011 + 0000 0001. Перший біт, маркер знака, автоматично регулюється.
Ця операція називається доповненням двох. Якщо вам цікаво, лист Вікіпедії розповість вам більше про причини цього позначення.
Тепер, коли ви це знаєте і знаєте це в арифметиці, A - B = A + (-B), Ви можете полегшити своє життя, виконуючи віднімання в двійковій системі.
Управління комою
Для обчислення чисел після десяткової коми в двійковій системі, як часто, логіка така ж, як і в десятковій. У десятковому значенні 0,1 дорівнює 1/10, або 10 -1; Від 0,01 до 10 -2 тощо.
Логічно, що в двійковому вигляді 0,1 бін дорівнює 2 -1 тощо. Кожен раз ділимо на два. Таким чином, для перших чотирьох рядків після коми ми маємо:
- 0,5
- 0,25
- 0,125
- 0,0625
Залишається лише з’ясувати, як зобразити кому. Секрет справді криється в науковому письмі.
Фіксована точка
Досить визначити положення десяткової коми, і ми миттєво дізнаємось значення числа. Наприклад, для числа, що зберігається в одному байті, тобто восьми бітах, якщо ми довільно визначимо положення десяткової коми перед тим, як після четвертого біта, тоді ми знаємо, що 0110 1001 = 0110 1001.
Це надзвичайно просто. Такий спосіб здійснення дій називається фіксованою точкою, оскільки положення точки відомо заздалегідь. Недоліком цього методу є те, що для числа з кількома десятковими знаками ви втрачаєте значний простір для зберігання. Якщо число, про яке йде мова, 0110 1000, ми втрачаємо три біти "без потреби".
Фіксована точка все ще використовується. На недорогих процесорах - мікроконтролерах - які мають лише можливість обробляти цілі числа та фіксовані коми, це єдине рішення. Крім того, в деяких ситуаціях фіксована точка може збільшити швидкість виконання або підвищити точність розрахунків.
Плаваюча крапка
Щоб подолати цю проблему втрати простору, спричиненої фіксованою точкою, ми використовуємо метод запису з плаваючою точкою. Це написання представляє числа наступним чином: знак × мантіса × основа показника . Положення коми зафіксовано в мантисі. Потім ми змушуємо його плавати, змінюючи показник ступеня.
Це точно як наукові та інженерні позначення. Таким чином, для одного і того ж розміру зберігання з чотирьох цифр, наприклад, ми можемо зберігати 1234, а також 1.234 або 0.1234, достатньо вказати, використовуючи експонент, куди ставиться кома.
IEE754
Є ще кілька проблем. З одного боку, як домовитись про положення коми в мантисі? З іншого боку, оскільки експонентом може бути відносне ціле число (ціле число зі знаком), знаком також слід керувати на цьому рівні.
Без стандарту кожен виробник призводить до внутрішнього впровадження. Отже, перенесення програмного забезпечення з однієї машини на іншу є складним через різницю у внутрішніх поданнях та поведінці чисел із плаваючою комою.
Округлення
Стандарт визначає чотири типи округлення:
- до негативної нескінченності,
- до позитивної нескінченності,
- до нуля,
- до найближчих.
Перші три раунди використовуються для представлення чисел, які перевищують межі зберігання або точності формату подання чисел. Таким чином, якщо ми можемо зберегти до мільярда, а результат операції перевищує це число, то оголошений результат буде до позитивної нескінченності.
Найближчим є природний режим округлення, саме це ми маємо на увазі, коли думаємо про округлення числа. Стандарт вказує для цього режиму, що якщо число знаходиться між двома, воно округляється до найближчого значення з найменшим значущим бітом при нулі (режим округлення за замовчуванням).
Точність
Точність визначається розміром мантиси. Не плутайте точність та амплітуду. Точність визначається розміром мантиси, тоді як амплітуда визначається розміром базового показника.
Якщо взяти за приклад науковий запис у базі 10, то для письма з трьома цифрами після десяткової коми і цілим показником, що стосується цифри, точність дорівнює чотирьом цифрам, але ми можемо представити порядки величини від + 1,999 М до -1,999 млн.
Однак ми усвідомлюємо, що ми не зможемо мати точність до одиниць на мільярд. Максимум, який можна зберегти, становить 1,999e9, і навіть при меншому значенні, наприклад 1,123e9, точність недоступна нижче мільйонів: 1,123e9 = 1 123 000 000.
Зменшуючи порядок величини, ми, звичайно, маємо точнішу точність. Отже, 1,123e2 = 112,3 і 1,123e-9 дорівнює 0,000000001123.
Таким чином, стандарт визначає чотири формати для подання чисел з плаваючою комою в базі 2:
- одинарна точність (також звана binary32),
- одинарна розширена точність,
- подвійна точність (також звана binary64),
- розширена подвійна точність.
Ми побачимо лише одинарну та подвійну точність, які є найбільш широко використовуваними (розширена одиночна точність застаріла на сьогодні). Нагадаємо, що значення отримується в результаті операції знак x мантиса x базовий показник . База тут завжди 2.
Стандарт підходить до десяткового наукового позначення, тому перший біт мантиси завжди дорівнює 1, а кома ставиться після цього 1.
Ця конвенція дає змогу відмовитися від фактичного написання, перший біт мантиси є неявним, а потім дає змогу отримати трохи точності. Таким чином, для 23-бітної мантиси точність становить 24 біта.
| Проста точність | 32 біт | 1 біт | 8 біт | 23 біти | 24 біти | ± 7 |
| Подвійна точність | 64 біт | 1 біт | 11 біт | 53 біти | 54 біти | ± 16 |
Ми виявили, що для формату подвійної точності мантиса дуже розширена, тоді як показник - меншою мірою. Це виправдано прагненням збільшити точність більше, ніж амплітуда представлених порядків.
Зсув експоненти
Як ми вже бачили, показник степеня є відносним цілим числом, тому він може бути додатним або від’ємним. Однак ні доповнення двох, ні правило бітового знака не використовуються для визначення знака степеня. Це зробило б порівняння чисел складнішим, а отже і менш ефективним.
Потім ми використовуємо a зміщення експоненти додавши його 2 (кількість бітів показника ступеня - 1) - 1. Цей зсув використовується для зберігання експоненти як без знака.
Спочатку ця розбіжність може здатися неясною. Однак візьмемо приклад: у випадку binary32 показник експоненти кодується на 8 бітах. Тому формула стає 2 8 - 1 - 1 = 128 - 1 = 127. Таким чином, -127, зміщений до значення нуль, використовується для нуля, значення -126 до -1 кодуються інтервалом від 1 до 126 (126 - 127 = -1) і вищі значення, що йдуть від 127 до 255 позитивних чисел коду в діапазоні від 1 до 128.
Ми знаємо, що для 8 бітів можливі 256 значень, наше правило дозволяє мати таку саму амплітуду, як якщо б ми використовували найбільш значущий біт для знака, тобто 27 значень = 128. 128 підписаних представляє 128 х 2 = 256 значення. З нашим зміщенням ми маємо 127 негативів плюс 128 позитивів плюс нуль або 256 значень !
Денормалізовані числа
Ми бачили, що наше позначення ігнорує перший біт мантиси, кажуть, що воно неявне, оскільки воно завжди одне. В реальності, цей найбільш значущий біт визначається значенням зсунутого показника. Якщо мантиса не дорівнює нулю, а зміщений показник дорівнює нулю, тоді вона дорівнює нулю, і число називається денормалізованим.
Цей запис чисел дозволяє отримати точність у поданні дуже малих чисел, що наближаються до нуля. Денормалізовані числа забезпечують безперервність за допомогою стандартизованих чисел.
Ось таблиця невеликого порядку, скопійована зі сторінки Вікіпедії на денормалізовані числа для простої точності.
| Нуль | 0000 0000 | 000 0000 0000 0000 0000 0000 | 0,0 | - |
| Менший денормалізоване число | 0000 0000 | 000 0000 0000 0000 0000 0001 | 1,4 × 10 −45 | 1,4 × 10 −45 |
| Наступне денормалізоване число | 0000 0000 | 000 0000 0000 0000 0000 0010 | 2,8 × 10 −45 | 1,4 × 10 −45 |
| Наступне денормалізоване число | 0000 0000 | 000 0000 0000 0000 0000 0011 | 4,2 × 10 −45 | 1,4 × 10 −45 |
| ... | ... | ... | ... | ... |
| Найбільше денормалізоване число | 0000 0000 | 111 1111 1111 1111 1111 1111 | 1,175 494 21 × 10 −38 | 1,4 × 10 −45 |
| Менший стандартизоване число | 0000 0001 | 000 0000 0000 0000 0000 0000 | 1,175 494 21 × 10 −38 | 1,4 × 10 −45 |
| Наступний стандартизований номер | 0000 0001 | 000 0000 0000 0000 0000 0001 | 1,175 494 21 × 10 −38 | 1,4 × 10 −45 |
Особливі випадки
Як ми щойно побачили, якщо зсунутий показник дорівнює нулю, число денормалізується. Інші особливі випадки дозволяють представляють спеціальні числа.
Якщо зсунутий показник дорівнює нулю, а мантиса також дорівнює нулю, це нульове значення, яке може бути +0 або -1 залежно від знакового біта.
Більше того, для e представляє розмір кодування експоненти, якщо показник дорівнює 2-й - 1 - або його найвище значення, 2 8 - 1, так 255 у випадку одиничної точності - і мантиса також дорівнює нулю, це нескінченність; + або - залежно від знакового біта.
Нарешті, якщо показник степеня є 2-й - 1 а мантиса є ненульовою, тоді вона є Ні, результат недійсної операції (наприклад, ділення на нуль).
Невелика підсумкова таблиця.
| Нулі | 0 | 0 |
| Денормалізовані числа | 0 | відрізняється від 0 |
| Нормовані числа | 1 до 2 - 2 | будь-який |
| Нескінченний | 2-й - 1 | 0 |
| NaNs | 2-й - 1 | відрізняється від 0 |
Округлення
Ми пояснили, як десяткові числа обчислюються у двійковому вигляді. Кожного разу це від’ємний ранг потужності основи: 2 -1 тощо. Будь-яке раціональне число можна виразити у дробовій формі.
Однак, щоб подання було скінченним, прості числа, що складають знаменник, повинні бути знайдені при розкладанні основи на множники. Це пояснення, визнаючи, досить складне, візьмемо конкретний приклад.
Таким чином, 1/2, 3/5 або 4/10 мають скінченні подання, оскільки 2 і 5 є основними множниками 10. Однак 1/3, 2/7 або 5/9 не мають скінченних подань, оскільки 3 і 7 є простих чисел не до степеня 10. Просте число, розкладене на множники 9, що становить 3 x 3, 3, не є простим числом основи.
В основі 2 це означає, що можна представити лише числа, знаменник яких має ступінь двох. Дійсно, два є простим числом, воно ділиться лише на одне і саме на себе.
Таким чином, 1/10, яке представлене 0,1 у десятковій точці, не має точного подання у двійковому вигляді, а також 1/3. Точні подання у двійковій системі насправді рідше, ніж у десятковій, оскільки в десятковій множник на прості числа повинен містити 2 та/або 5, тоді як у двійковій формі можна приймати лише 2.
Роблячи це, у десятковому порядку ми представляємо кінцевим способом 1/2, 1/4, 1/5, 1/8 і 1/10 тощо, у двійковому вигляді - кінцевим способом 1/2, 1/4, 1/8, 1/16, 1/32, 1/64 тощо.
Це обов'язково призводить до використання округлення для подання чисел. Поки ви виконуєте операції з цими числами, помилки округлення накопичуються і можуть призвести до нерівних результатів. Ось чому в JavaScript, наприклад, 0,1 + 0,2 = 0,30000000000000004.
Інші мови, такі як PHP, відображають результат відповідним чином, але ми помічаємо, що це лише округлення вгору при відображенні змінної, тому що якщо ми робимо var_dump ((0,1 + 0,2) === 0,3); ", ми отримуємо bool (помилковий) .
Швидкість обчислень
Числа з плаваючою комою настільки важливі в інформатиці, що їх використовують для вимірювання потужності комп’ютерів. Швидкість обчислювальної техніки комп'ютерів, особливо суперкомп'ютерів, вимірюється в FLOPS, кількість операцій з плаваючою точкою, яку машина може виконувати в секунду.
Він менше використовується для оцінки потужності персональних комп’ютерів, проте це більш виразний показник, ніж тактова частота. Якщо провести паралель з двигунами внутрішнього згоряння, це все одно, що рекламувати робочий об’єм двигуна, а не його кінську силу, хоча існує взаємозв’язок, кінська сила є кращим показником.
Якщо ви хочете оцінити кількість FLOPS у вашої машини, погляньте на це обговорення [fr].
У наступному розділі ми відпустимо цифри, щоб поговорити про букви та їх кодування за допомогою Unicode !
Приєднуйтесь до обговорення !
Квентін Бусуттіл - ліцензія Creative Commons BY-NC-ND