Программирование c способ создания десятичного числа макс. 32-битного числа со знаком (Python3) - PullRequest
1 голос
/ 24 марта 2020

Постановка проблемы и история вопроса

Я пишу функцию с заданной строкой, содержащей одно значение с плавающей запятой, например, '3.14159'.

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

Из-за проблем точности с плавающей запятой я хотел использовать Decimal объект для сравнения.

Что я спрашиваю:

Как мне создать Decimal со значением самого большого 32-разрядного числа со знаком в нем?

Это будет использоваться для сравнения.

Что я пробовал:

После просмотра этой статьи в Википедии: https://en.wikipedia.org/wiki/Single-precision_floating-point_format

.. ... который сообщает, что имеется 23 коэффициента, 8 экспонент и 1 знак, я написал следующий код:

from decimal import Decimal


def is_single(value):
    d_value = Decimal(value)

    _23bit_max_bin = '1' * 23  # '11111111111111111111111'
    _23bit_max_dec = int(_23bit_max_bin, 2)  # 8388607

    _coeffient_tuple = tuple([int(d) for d in str(_23bit_max_dec)])  # (8, 3, 8, 8, 6, 0, 6)

    _exponent_bin = '1' * 8  # '11111111'
    _exponent_dec = int(_exponent_bin, 2)  # 255

    _dec_tuple = (0, _coeffient_tuple, _exponent_dec)  # (1, (8, 3, 8, 8, 6, 0, 6), 254)
    max_single_size = Decimal(_dec_tuple)  # Decimal('8.388607E+261')

    print(max_single_size)  # Decimal('8.388607E+261')

    return d_value < max_single_size


is_single('3.14159')

... я надеюсь, что смогу взять максимальные двоичные значения для коэффициент и экспонента, преобразовать их в десятичные значения, а затем создать Decimal объект с использованием результатов.

Проблема заключается в том, что результирующее значение действительно похоже на значения, указанные на той же странице википедии, то есть 8.388607E+261 (мое значение) не похоже на 1.1754942107 ×10−38 (вики)

Мне кажется, что я что-то упускаю ... может быть, уже слишком поздно?

Показания:

Спасибо

- Тим

Ответы [ 2 ]

2 голосов
/ 24 марта 2020

… границы 32-битного числа со знаком…

Представляемые числа в float находятся в диапазоне от −∞ до + ∞, поэтому все конечные числа находятся в диапазоне , Но я предполагаю, что вы хотите рассмотреть конечный диапазон типа float, а не полный диапазон.

_23bit_max_bin = '1' * 23  # '11111111111111111111111'
_23bit_max_dec = int(_23bit_max_bin, 2)  # 8388607

Это дает вам максимальное значение поля значимости и в кодировке float, интерпретируемое как двоичное целое число. Это не максимальное значение представленного значения.

Предполагая, что поле экспоненты не является ни всеми нулями, ни всеми, представленное значение представляет собой число, двоичное число которого равно «1», за которым следует «.» следуют биты значимого поля. Таким образом, максимальное значение равно 1.11111111111111111111111 2 = 2 1 -2 −23 .

exponent_bin = '1' * 8  # '11111111'

Это дает вам максимальное значение поле экспоненты. Однако максимальное значение поля экспоненты используется для кодирования бесконечностей и NaN, а не конечных чисел. Максимальное значение поля экспоненты, используемого для конечных чисел, составляет 11111110 2 (254 10 ). Кроме того, представленный показатель представляет собой значение поля показателя (интерпретируемого как двоичное целое число) минус 127. Таким образом, максимальный показатель составляет 254−127 = 127.

_dec_tuple = (0, _coeffient_tuple, _exponent_dec)  # (1, (8, 3, 8, 8, 6, 0, 6), 254)

, который использует 254 в качестве показателя 10 Показатель степени в формате float представляет собой показатель степени 2.

Максимальное конечное значение, представляемое в float, представляет собой максимальное значение, умноженное на 2 на степень максимального показателя степени, поэтому оно равно (2 1 −2 −23 ) • 2 127 = 2 128 - 2 104 = 340282346638528859811704183484516925440. Давайте назовем это число M .

Тем не менее, при определении, находится ли десятичная цифра в границах, вы должны решить, хотите ли вы подумать:

  • число в - M до + M включительно или
  • число находится в диапазоне, где обычное округление при преобразовании в float даст значение в - M до + M включительно ( т.е. , это д oes не округляется до бесконечности).

В последнем случае, в режиме округления до ближайшего, желаемое ограничение составляет 2 128 - 2 104 + 2 103 = 2 128 - 2 103 = 340282356779733661637539395458142568448, эксклюзив. Этот «полушаг», 2 103 , к тому месту, где будет следующий представимый номер, если диапазон экспонент будет продолжать двигаться, - это то, где метод округления к ближайшему изменяется между округлением в меньшую сторону и округлением в большую сторону. В случае, когда в ie именно в этой точке, оно округляется до числа с четным значащим и битом, который будет восходящим. Таким образом, вы хотите исключить его, следовательно, интервал является исключительным, а не включающим.

Как правило, если точность равна p (поле значимостей составляет p −1 бит ) и поле экспоненты имеет w бит, смещение экспоненты составляет 2 w -1 -1, максимальный показатель такой же и наибольшее представимое конечное значение является (2-2 1− p ) • 2 2 w −1 −1 = (1 −2 - p ) • 2 2 w -1 .

0 голосов
/ 24 марта 2020

На самом деле: 3.4028234664 × 10 ^ 38

Попробуйте найти следующие числа:

2 ^ 128 = 340282366920938463463374607431768211456

10 ^ 38 = 10000000000000000000000000000000000

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...