сколько именно цифр может содержать float8, float16, float32, float64 и float128? - PullRequest
2 голосов
/ 09 июня 2019

Простите, что задал такой тупой вопрос, но я не смог найти ответов в Интернете.

Документация dtype от Numpy показывает только экспоненты X битов и мантиссу Y битов для каждого типа с плавающей запятой, но я не могу перевести, какие экспоненты X битов и мантиссу Y битов точно в количество цифр до / после десятичной дроби точки. Есть ли какая-нибудь простая формула / таблица для поиска?

Заранее спасибо

1 Ответ

5 голосов
/ 09 июня 2019

Это не так просто, как обычно ожидается. Для точности мантиссы обычно существует два значения:

  1. Учитывая значение в десятичном представлении, сколько десятичных цифр может быть гарантированно сохранено при преобразовании из десятичного в выбранный двоичный формат и обратно (с округлением по умолчанию).

  2. Учитывая значение в двоичном формате, сколько десятичных цифр необходимо, если значение преобразуется в десятичный формат и обратно в исходный двоичный формат (опять же, с округлением по умолчанию), чтобы получить исходное значение без изменений.

В обоих случаях десятичное представление рассматривается как независимое от используемого показателя, без начальных и конечных нулей (например, все 0,0123e4, 1,23e2, 1,2300e2, 123, 123.0, 123000.000e-3 являются 3 цифрами).

Для 32-разрядного двоичного числа с плавающей запятой эти два размера составляют 6 и 9 десятичных цифр соответственно. В C это FLT_DIG и FLT_DECIMAL_DIG. (Это странно, что 32-разрядное число с плавающей запятой хранит 7 десятичных цифр для общего количества всех чисел, но есть исключения.) В C ++ посмотрите std :: numeric_limits :: digits10 и std :: numeric_limits :: max_digits10 соответственно.

Для 64-разрядного двоичного числа с плавающей запятой это 15 и 17 (DBL_DIG и DBL_DECIMAL_DIG соответственно; и std :: numeric_limits :: {digits10, max_digits10}).

Общие формулы для них (thx2 @MarkDickinson)

  • $ {формат} _DIG (цифры 10): floor((p-1)*log10(2))
  • $ {format} _DECIMAL_DIG (max_digits10): ceil(1+p*log10(2))

где p - количество цифр в мантиссе (включая скрытую для нормализованного случая IEEE754).

Кроме того, комментарии с некоторым математическим объяснением на C ++ числовые ограничения страница:

Стандартный 32-битный тип IEEE 754 с плавающей запятой имеет 24-битную дробную часть (записано 23 бита, подразумевается один), что может указывать на то, что он может представлять 7-значные десятичные дроби (24 * std :: log10 (2) 7.22), но относительные ошибки округления неоднородны, и некоторые значения с плавающей запятой с 7 десятичными цифрами не сохраняются при преобразовании в 32-разрядные числа с плавающей запятой и обратно: наименьший положительный пример - 8,589973e9, который становится равным 8,589974e9 после обратного хода. Эти ошибки округления не могут превышать один бит в представлении, и цифры 10 вычисляются как (24-1) * std :: log10 (2), что составляет 6,92. Округление приводит к значению 6.

Ищите значения для 16- и 128-битных операций с плавающей точкой в ​​комментариях (но посмотрите, что такое 128-битные операции с плавающей точкой в ​​реальном времени).

Для показателя степени это проще, потому что каждое из значений границы (минимальное нормированное, минимальное денормализованное, максимальное представленное) является точным и может быть легко получено и напечатано.

@ PaulPanzer предложил numpy.finfo. Он дает первое из этих значений ({format} _DIG); может быть, это то, что вы ищете:

>>> numpy.finfo(numpy.float16).precision
3
>>> numpy.finfo(numpy.float32).precision
6
>>> numpy.finfo(numpy.float64).precision
15
>>> numpy.finfo(numpy.float128).precision
18

но в большинстве систем (моей была Ubuntu 18.04 на x86-84) значение float128 сбивает с толку; это действительно для 80-битного x86 «расширенного» числа с 64-битным значением; Реальный IEEE754 float128 имеет 112 значащих и битов, поэтому реальное значение должно быть около 33, но numpy представляет другой тип под этим именем. См. здесь для деталей: в общем, float128 - заблуждение в numpy.

UPD3: вы упомянули float8 - в наборе IEEE754 такого типа нет. Можно представить такой тип для каких-то совершенно определенных целей, но его диапазон будет слишком узким для универсального использования.

...