以编程方式创建带符号 32 位浮点数的最大值 (Python3)

Programmatic way to create Decimal of max of signed 32-bit float (Python3)

问题陈述和背景

我正在编写一个函数,它被赋予包含单个浮点值的字符串,例如“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(wiki)

我觉得我好像错过了什么......也许今天已经太晚了?

读数:

实际上是:3.4028234664 × 10^38

尝试查找以下数字:

2^128 = 340282366920938463463374607431768211456

10^38 = 100000000000000000000000000000000000000

… the boundaries of the a signed 32-bit float…

float中可表示的数的范围是-∞到+∞,所以所有的有限数都在这个范围内。但我想你想考虑 float 类型的有限范围,而不是整个范围。

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

这为您提供了 float 编码的有效数字字段的最大值,解释为二进制整数。那不是所表示的尾数的最大值。

假设指数字段既不全为零也不全为1,则表示的有效位数是二进制为“1”后跟“.”的数。其次是有效位域的位。所以最大有效数是 1.111111111111111111111112 = 21−2−23.

exponent_bin = '1' * 8  # '11111111'

这为您提供了指数字段的最大值。但是,指数字段的最大值用于编码无穷大和 NaN,而不是有限数。用于有限数的指数字段的最大值是 111111102 (25410)。此外,表示的指数是指数字段(解释为二进制整数)的值减去 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的最大指数次方,所以是(21−2−23) • 2127 = 2128 − 2104 = 340282346638528859811704183484516925440。我们称这个号码为 M.

但是,在判断一个十进制数是否在范围内时,你应该考虑是否要考虑:

  • 数字在-M至+M之间,含,或
  • 该数字在转换为 float 后正常舍入将产生 −M 到 +M[=88 之间的值的范围内=],包括在内(,它不会四舍五入为无穷大)。

在后一种情况下,在舍入到最近的模式中,您想要的限制是 2128 − 2104 + 2103 = 2128 − 2103 = 340282356779733661637539395458142568448,独占。那个“半步”,2103,朝向下一个可表示的数字,如果指数范围继续前进,就是舍入到最近的方法在向下舍入和向上舍入之间变化的地方.如果恰好在该点上出现平局,则它四舍五入到具有偶数有效位的数字,这将是向上的。所以你想排除它,因此间隔是排他的而不是包含的。

一般情况下,如果精度为p(有效位有p−1位),指数位有w位,指数偏差为2w−1−1,最大指数相同,最大可表示的有限值是 (2−21−p) • 22 w−1−1 = (1−2p) • 2 2w−1.