【问题标题】:Why doesn't float() throw an exception when the argument is outside the range of a Python float?当参数超出 Python 浮点数的范围时,为什么 float() 不抛出异常?
【发布时间】:2023-02-02 19:06:19
【问题描述】:

我正在使用Python 3.10并且我有:

a = int(2 ** 1023 * (1 + (1 - 2 ** -52)))

现在,a的值是double precision floating point format中的最大整数值。

所以,我期待 float(a + 1) 给出 OverflowError 错误,如 here 中所述:

如果参数超出 Python 浮点数的范围,则会引发 OverflowError。

但是,令我惊讶的是,它并没有抛出错误,而是愉快地返回

1.7976931348623157e+308

看起来像sys.float_info.max

我也做float(a + 2)float(a + 3)float(a + 4)等,但它仍然返回1.7976931348623157e+308。只有在我执行 float(a + a) 之后它才会抛出预期的异常:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: int too large to convert to float

那么,这可能是什么原因呢?

【问题讨论】:

  • 对我来说,它在 a+a 之前抛出。
  • @KellyBundy 我只查看float(a + 10)。我的观点不是关于 kfloat(a + k) 中有多大,而是为什么它不针对每个 k &gt;= 1 抛出。
  • 是的,但它似乎在 a+(a>>53) 附近开始失败,这可能会提供一些见解。
  • 可能是由可变浮点密度引起的:在 0 附近非常高,并且在“间隔边缘”附近非常低,其中在 2 个“连续”值之间(仅相差最低有效位- 尾数)有一个巨大的差距。
  • 对我来说失败的最小自然数:a + 2**970

标签: python floating-point


【解决方案1】:

正如所评论的那样,2**970 是四舍五入的最小加法。这是有道理的,如下所示:

 1023 =exp
-  52 =n, where the "smallest" field is 2**-n
-----
  971
                                        L G RS
so, the largest is: (2**1023)*1.111...111(1)00
                                123...012 3 45  // bit #s
                                ^     555 5 55
                          2**1022       ^ ^
                                        ^ ^
                                  2**-971 ^
                                          ^
                                          ^
                                          2**970

...因此,根据 LGRS=1100 值,添加 2**970 将向上舍入。这些是 IEEE 754 规范中的最低有效位、保护位、舍入位和粘滞位。

这可以在 python 中演示如下:

>>> import sys
>>> print("%100.10f" % (sys.float_info.max))
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0000000000
>>> # note that even though this is even in base 10, the significand is odd in binary since the Least significant bit is 1
... 
>>> print("%100.10f" % (sys.float_info.max+2**970))
                                                                                                 inf
>>> print("%100.10f" % (sys.float_info.max+2**969))
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0000000000
>>> 

【讨论】:

    猜你喜欢
    • 2013-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 2020-09-30
    相关资源
    最近更新 更多