Программный способ создания десятичного числа макс. 32-битного числа со знаком (Python3)

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

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

То, что я хотел бы сделать, это оценить, находится ли этот float в границах подписанного 32-битного float (также 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 = Ƈ' * 23  # �'
    _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 = Ƈ' * 8  # �'
    _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(Ǝ.388607E+261')

    print(max_single_size)  # Decimal(Ǝ.388607E+261')

    return d_value < max_single_size


is_single(Ɖ.14159')

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

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

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

Показания:

Спасибо

Тим

Всего 2 ответа


... границы подписанного 32-разрядного числа с плавающей точкой ...

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

_23bit_max_bin = Ƈ' * 23  # �'
_23bit_max_dec = int(_23bit_max_bin, 2)  # 8388607

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

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

exponent_bin = Ƈ' * 8  # �'

Это дает вам максимальное значение поля экспоненты. Однако максимальное значение поля экспоненты используется для кодирования бесконечностей и 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 включительно ( т. е. оно не округляется до бесконечности).

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

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


Это на самом деле: 3.4028234664 × 10 ^ 38

Попробуйте поискать следующие цифры:

2 ^ 128 = 340282366920938463463374607431768211456

10 ^ 38 = 100000000000000000000000000000000000000


Есть идеи?

10000