При перетворенні з цілої на одиничну може втратити точність


27

Коли я перейшов до частини, я читав статтю від Microsoft про розширювані конверсії та обмеження параметрів

Такі конверсії можуть втратити точність:

  • Цілий до одинакового
  • Довгий до одинарного або подвійного
  • Десяткові до одинарних або подвійних

Однак ці перетворення не втрачають інформації чи масштабів.

.. але згідно з іншою статтею щодо типів даних ,

  • Тип цілого числа може зберігати від -2.147.483.648 до 2.147.483.647 і

  • Один тип можна зберігати

    • 1,401298E-45 до 3,4028235E + 38 для додатних чисел,
    • і -3,4028235E + 38 до - 1,401298E-45 для від’ємних чисел

.. тому Single може зберігати набагато більше номерів, ніж Integer. Я не міг зрозуміти, в якій ситуації таке перетворення з Integer в Single може втратити точність. Може хтось пояснить, будь ласка?

Відповіді:


87

Одномісний може зберігати набагато більше номерів, ніж Integer

Ні, не може. Обидва Singleі Integerє 32-бітовими, це означає, що обидва можуть зберігати однакову кількість чисел, а саме 2 32 = 4294967296 різних чисел.

Оскільки діапазон від Singleявно більше , ніж це, то відразу видно (через Pigeonhole принципу ) , що він не може представляти всі числа в межах цього діапазону.

А оскільки діапазон Integerточно такого ж розміру, як максимальний обсяг чисел, який Integerі Singleможе представляти, але Singleтакож може представляти числа поза цим діапазоном, зрозуміло, що він не може представляти всі числа всередині діапазону Integer.

Якщо є кілька цифр, Integerякі не можуть бути представлені в Single, перетворення з Integerна Single повинно бути здатне втрачати інформацію.


3
+1 для цього чудового пояснення того, чому це повинно бути так, навіть якщо питання насправді було коли ("в якій ситуації") це трапляється ...
подвійно

21
@doubleYou: 4261412864 з 4294967296 Integers (99.2%) не може бути представлений як Single, тому "коли" є "майже завжди".
Йорг W Міттаг

2
Якщо ви хочете бути точнішими, Singleможна представити лише 4,278,190,079 різних чисел. SingleЗначення являє собою число , якщо і тільки якщо збережене показник не 255, що означає , що є 255 * 2 ^ 24 Singleроків , які представляють собою число. З них два з них представляють однакове число (а саме, нуль), а інші - різні числа.
Таннер Світт

10
en.wikipedia.org/wiki/Single-precision_floating-point_format добре пояснює обмеження для IEEE754 бінарних32. Цілі числа в [-16777216,16777216](2 ^ 24 = значуща ширина) можуть бути точно представлені. Більші числа округляються до найближчого кратного 2, 4, 8, ... залежно від їх величини.
Пітер Кордес

14
"Це означає, що обидва можуть зберігати однакову кількість цифр" - Це не означає, що. Це означало б лише те, що якщо обидва типи мають точно однакову кількість способів зберігання кожного числа. І це не так; наприклад, Singleє два способи зберігання нуля. Так Singleнасправді може представляти менше різні числа , ніж Integer.
Конрад Рудольф

28

Типи з плаваючою комою (такі як Одинарний та Подвійний) представлені в пам'яті знаком, мантісою та експонентом. Розгляньте це як наукове позначення:

Sign*Mantissa*Base^Exponent

Вони - як ви можете очікувати - використовують базу 2. Є інші налаштування, які дозволяють представляти нескінченність і NaN, а показник зміщений (повернеться до цього), і стенограма для мантіси (повернеться до цього теж) . Шукайте стандарт IEEE 754, який охоплює його представлення та операції для отримання більш детальної інформації.

Для наших цілей ми можемо уявити це як двійкове число "mantissa" та "показник", який підказує, куди слід поставити десятковий роздільник.


У випадку з одиноким, у нас є 1 біт для знака he, 8 для експонента і 23 для mantissa.

Тепер справа в тому, що ми будемо зберігати мантію з найзначнішої цифри. Пам’ятайте, що всі нулі зліва не стосуються. І даючи, що ми працюємо у двійковій формі, ми знаємо, що найзначніша цифра - 1 ※. Ну, оскільки ми це знаємо, зберігати його не треба. Завдяки цій стенограмі ефективний діапазон мантіси становить 24 біта.

※: Якщо число, яке ми зберігаємо, дорівнює нулю. Для цього у нас будуть всі біти встановлені в нуль. Однак, якщо ми спробуємо інтерпретувати, що під описом, який я дав, у вас буде 2 ^ 24 (неявний 1), помножений на 1 (2 на силу показника 0). Отже, щоб виправити це, показник нуля - це особливе значення. Існують також спеціальні значення для зберігання нескінченності та NaN в експоненті.

Відповідно до зміщення експонента - окрім уникнення спеціальних значень - його зміщення дозволяє розмістити десяткову точку до початку мантіси або після її закінчення, не потребуючи позначення експонента.


Це означає, що для великих чисел тип з плаваючою комою поставить десяткову точку за межі кінця мантіси.

Пам’ятайте, що мантіса - це 24-бітове число. Він ніколи не представлятиме 25-бітове число ... у нього немає цього додаткового біта. Таким чином, одинарний не може розрізняти 2 ^ 24 і 2 ^ 24 + 1 (це перші 25 бітові числа, і вони відрізняються від останнього біта, який не представлений в одиничному).

Таким чином, для цілих чисел діапазон одиничного становить -2 ^ 24 до 2 ^ 24. І намагаючись додати 1 до 2 ^ 24, це призведе до 2 ^ 24 (тому що, що стосується типу, 2 ^ 24 і 2 ^ 24 + 1 мають однакове значення). Спробуйте в Інтернеті . Ось чому відбувається втрата інформації при перетворенні з цілого на одиничне. І тому також цикл, який використовує одинарний чи подвійний, насправді може бути нескінченним циклом, не помічаючи вас.


Це не є ідеальним поясненням неявного провідного 1біта в significand. Це має на увазі те , що поле зміщеного експонента не є нульовим . Субнормальні тварини (в т.ч.+-0.0 деннормальні), у тому числі мають провідний 0біт свого значення. Я думаю, ви могли б спростити, щоб просто розглянути 0.0цілком особливий випадок, але 0.0насправді слідує тим самим правилам кодування, що й інші субнормали.
Пітер Кордес

25

Ось фактичний приклад того, як при переході Integerдо системи Singleможе втратити точність:

SingleТип може зберігати всі цілі числа від -16777216 до 16777216 (включно), але вона не може зберігати всі цілі числа поза цього діапазону. Так , наприклад, він не може зберегти номер 16777217. В цьому відношенні, він не може зберігати будь- непарне число більше , ніж 16777216.

Ми можемо використовувати Windows PowerShell, щоб побачити, що станеться, якщо ми перетворимо Integerна a Singleі назад:

PS C:\Users\tanne> [int][float]16777213
16777213
PS C:\Users\tanne> [int][float]16777214
16777214
PS C:\Users\tanne> [int][float]16777215
16777215
PS C:\Users\tanne> [int][float]16777216
16777216
PS C:\Users\tanne> [int][float]16777217
16777216
PS C:\Users\tanne> [int][float]16777218
16777218
PS C:\Users\tanne> [int][float]16777219
16777220

Зауважте, що 16777217 округлили до 16777216, а 16777219 округлили до 16777220.


4
І зі збільшенням масштабу відстань між найближчими представниками floats зростає як сили. en.wikipedia.org/wiki/…
Пітер Кордес

12

Типи з плаваючою точкою схожі на "наукові позначення" у фізиці. Число розбивається на знаковий біт, експонент (множник) і мантісу (значні цифри). Оскільки збільшення величини збільшується, розмір кроку також збільшується.

Плаваюча точка з однією точністю має 23 біти мантіси, але є "неявна 1", тому мантісса ефективно 24 біта. Тому всі цілі числа з величиною до 2 24 можуть бути представлені точно в плаваючій точці з однією точністю.

Над цим послідовно може бути представлена ​​менша кількість.

  • Від 2 24 до 2 25 можуть бути представлені лише парні числа.
  • Від 2 25 до 2 26 можуть бути представлені лише кратні з 4.
  • Від 2 26 до 2 27 можуть бути представлені лише кратні 8.
  • Від 2 27 до 2 28 можуть бути представлені лише кратні 16
  • Від 2 28 до 2 29 можуть бути представлені лише кратні 32
  • Від 2 29 до 2 30 можуть бути представлені лише кратні 64
  • Від 2 30 до 2 31 можуть бути представлені лише кратні 128

Таким чином, з 2 32 можливих 32-бітових цілих цілих значень лише 2 * (2 24 + 7 * 2 23 ) = 9 * 2 24 можуть бути представлені в єдиній плаваючій точці точності. Це 3,515625% від загальної кількості.


8

Одноточні поплавці мають 24 біти точності. Все, що над цим, округляється до найближчого 24-бітного числа. Це може бути простіше зрозуміти в десяткових наукових позначеннях, але пам’ятайте, що фактичні поплавці використовують двійкові.

Скажімо, у вас є 5 десяткових цифр пам'яті. Ви можете використовувати такі, як звичайний неподписаний int, що дозволяє мати будь-яке число від 0 до 99999. Якщо ви хочете мати можливість представляти більші числа, ви можете використовувати наукові позначення і просто виділити дві цифри, щоб бути експонентом, так тепер ви можете представляти що завгодно від 0 до 9,99 х 10 99 .

Однак найбільше число, яке ви можете точно представляти, становить лише 999. Якщо ви намагалися представити 12345, ви можете отримати 1,23 х 10 4 або 1,24 х 10 4 , але ви не можете представити жодне з чисел між ними, оскільки ви не вистачає цифр.


3
Використання десяткових цифр - це приємна ідея, яка полегшує розуміння, але останній абзац трохи вводить в оману: насправді ви можете представляти числа вище 999, і ваш приклад показує це: 12300 буде 1,23 x 10 <sup> 4 <sup >. Що ви маєте на увазі, що починаючи з цього числа, виникають прогалини. Ви не хотіли б трохи перефразувати це?
Фабіо каже, що поверніть Моніку
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.