При преобразовании из целого числа в единичное может потеряться точность

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 может потерять точность. Может кто-нибудь объяснить, пожалуйста?

Виниций V
источник

Ответы:

87

Single может хранить гораздо больше чисел, чем Integer

Нет, не может. Оба Singleи Integer32-разрядные, что означает, что оба могут хранить одинаковое количество чисел, а именно 2 32 = 4294967296 различных чисел.

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

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

Если есть некоторые числа, Integerкоторые не могут быть представлены в Single, преобразование из Integerв Single должно быть способным к потере информации.

Йорг Миттаг
источник
3
+1 за это замечательное объяснение того, почему это должно иметь место, хотя вопрос был на самом деле, когда («в какой ситуации») это происходит ...
doubleYou
21
@doubleYou: 4261412864 из 4294967296 Integerс (99,2%) не могут быть представлены как Single, поэтому «когда» означает «почти всегда».
Йорг Миттаг
2
Если вы хотите быть более точным, Singleможете представить только 4 278 190 079 различных чисел. SingleЗначение представляет собой число , если и только если сохраненное показатель не 255, что означает , что есть 255 * 2 ^ 24 Singleлет , которые представляют собой число. Из них два представляют одно и то же число (а именно, ноль), а все остальные представляют разные числа.
Таннер Светт
10
en.wikipedia.org/wiki/Single-precision_floating-point_format хорошо объясняет ограничения для двоичного кода IEEE75432. Целые числа в [-16777216,16777216](2 ^ 24 = значимость и ширина) могут быть точно представлены. Большие числа округляются до ближайшего кратного 2, 4, 8, ... в зависимости от того, насколько они велики.
Питер Кордес
14
«Что означает, что оба могут хранить одинаковое количество чисел» - это не значит, что. Это будет означать только то, что, если оба типа имеют одинаковое количество способов хранения каждого числа. И это не так; например, Singleимеет два способа хранения нуля. Таким Singleобразом, на самом деле может представлять меньше отдельных чисел, чем Integer.
Конрад Рудольф
28

Типы с плавающей точкой (такие как Single и Double) представлены в памяти знаком, мантиссой и показателем степени. Думайте об этом как научная запись:

Sign*Mantissa*Base^Exponent

Они - как вы можете ожидать - используют базу 2. Существуют и другие твики, которые позволяют представлять бесконечность и NaN, а показатель степени смещен (вернется к этому) и сокращенный вариант мантиссы (вернусь к этому тоже) , Ищите стандарт IEEE 754, который охватывает его представление и операции для получения более подробной информации.

Для наших целей мы можем представить его как двоичное число «мантисса» и «показатель степени», который говорит вам, куда поместить десятичный разделитель.


В случае Single у нас есть 1 бит для знака, 8 для показателя степени и 23 для мантиссы.

Теперь дело в том, что мы будем хранить мантиссу из самой значимой цифры. Помните, что все нули слева не имеют значения. И учитывая, что мы работаем в двоичном формате, мы знаем, что самая значимая цифра - 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 - это одно и то же значение). Попробуйте онлайн . Вот почему при преобразовании целого числа в единичное происходит потеря информации. И это также, почему цикл, который использует одинарную или двойную, может на самом деле быть бесконечным циклом без вашего ведома.

Theraot
источник
Это не идеальное объяснение неявного ведущего 1бита в значении. Это подразумевается тем, что поле смещенной экспоненты не равно нулю . Субнормальные (или ненормальные) в том числе+-0.0 имеют ведущее 0значение. Я предполагаю, что вы могли бы упростить рассмотрение 0.0только особого случая, но на 0.0самом деле следует тем же правилам кодирования, что и другие субнормалы.
Питер Кордес
25

Вот фактический пример того, как преобразование из Integerв Singleможет потерять точность:

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

Мы можем использовать Windows PowerShell, чтобы увидеть, что произойдет, если мы преобразуем a 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 десятичных цифр памяти. Вы можете использовать такие, как обычные целые числа без знака, что позволяет иметь любое число от 0 до 99999. Если вы хотите иметь возможность представлять большие числа, вы можете использовать научную запись и просто выделить две цифры в качестве показателя степени, поэтому Теперь вы можете представлять что угодно между 0 и 9,99 х 10 99 .

Однако наибольшее число, которое вы можете точно представить, составляет сейчас только 999. Если вы попытались представить 12345, вы можете получить 1,23 x 10 4 или 1,24 x 10 4 , но вы не можете представить любое из промежуточных чисел, потому что вы не хватает цифр

Карл Билефельдт
источник
3
Использование десятичных цифр - хорошая идея, которая облегчает понимание, но последний абзац немного вводит в заблуждение: на самом деле вы можете представлять числа больше 999, и ваш пример показывает это: 12300 будет 1,23 x 10 <sup> 4 <sup >. Вы имеете в виду, что начиная с этого числа, есть пробелы. Не могли бы вы немного перефразировать это?
Фабио говорит восстановить Монику