我遇到过一些奇怪的事情并且无法解释。 在: 输出: 为什么它会变成 例如,如果我用 这是否意味着浮动上存在一种“软”限制 - 当超过时 - 将它们变成 添加 我知道有 我刚才有了一个想法并测试了一些东西: 这给了我: 这对我来说很奇怪...... x = 10.0
for i in range(10):
print(str(i) + " | " + str(x))
x *= x
0 | 10.0
1 | 100.0
2 | 10000.0
3 | 100000000.0
4 | 1e+16
5 | 1e+32
6 | 1.0000000000000002e+64
7 | 1.0000000000000003e+128
8 | 1.0000000000000005e+256
9 | inf
inf
?为什么不抛出异常?*=
替换最后一行中的**=
,那么在第二次迭代中它会引发OverflowError: (34, 'Result too large')
,这是有道理的(因为它只有10.000.000.000 ^ 10.000.000.000)。inf
?如果是这样,那么限制是什么,无论算术运算如何都是一样的?这不会意味着像inf == this_limit + anything
吗?sys.float_info.max
。这是限制吗?print(sys.float_info.max)
print(sys.float_info.max + 1)
print(sys.float_info.max * 2)
print(sys.float_info.max * 1.000000000000001)
print(sys.float_info.max * 1.0000000000000001)
1.7976931348623157e+308
1.7976931348623157e+308
inf
inf
1.7976931348623157e+308
答案 0 :(得分:6)
为什么它会变成inf?
因为即使是最大的有限浮点数,结果也太大了,所以它会溢出。
为什么不抛出异常?
因为Python在将inf / nan变成异常的时候不是很一致。一些操作提供例外。有些人给inf / nan。
这是否意味着浮子有一种“软”限制 - 当超过时 - 将它们变成inf?如果是这样,那么限制是什么,无论算术运算如何都是一样的?这不会暗示像inf == this_limit +任何东西吗?
在舍入后,任何大于1.7976931348623157e + 308的结果都会成为inf(或者如果Python感觉像是异常)。确切的限制不能表示为浮动;你实际上无法执行this_limit + anything
,因为尝试将this_limit
放入浮点数会将其舍入为1.7976931348623157e + 308。
答案 1 :(得分:3)
如果你在CPython(floatobject.c
)中检查浮点运算实现,你可以看到大多数操作只是推迟到C double
操作,例如在float_add
,{{3 }},或float_sub
:
static PyObject *
float_mul(PyObject *v, PyObject *w)
{
double a,b;
CONVERT_TO_DOUBLE(v, a);
CONVERT_TO_DOUBLE(w, b);
PyFPE_START_PROTECT("multiply", return 0)
a = a * b;
PyFPE_END_PROTECT(a)
return PyFloat_FromDouble(a);
}
结果a = a * b
是根据IEEE 754标准在CPU上计算的 - 在溢出的情况下禁止-inf
/ +inf
的默认结果(即结果不能存储在有限的32位float
或64位double
中。)
另外需要注意的是,IEEE 754中定义的五个浮点异常(如溢出)中的任何一个都可以(1)产生默认值并将异常信息存储在状态字,或者(2)如果启用FP异常陷阱,则发出SIGFPE
信号(参见float_mul
)。
在Python中,陷阱是GNU lib C docs on FP exceptions,因此程序以不间断模式运行。
这意味着,反过来, float_mul
例程上的溢出结果将默认为float inf
(如IEEE 754中所定义)和Python只会返回PyFloat_FromDouble(a)
,a
为inf
。
另一方面,如果我们检查never enabled(下面的缩短版本):
static PyObject *
float_pow(PyObject *v, PyObject *w, PyObject *z)
{
...
errno = 0;
PyFPE_START_PROTECT("pow", return NULL)
ix = pow(iv, iw);
PyFPE_END_PROTECT(ix)
Py_ADJUST_ERANGE1(ix);
if (errno != 0) {
PyErr_SetFromErrno(errno == ERANGE ? PyExc_OverflowError :
PyExc_ValueError);
...
}
...
}
我们可以看到x **= x
的结果为inf
,如果不是附加的状态字(〜{{ 1}})检查 - 并在基础errno
溢出的情况下引发Python OverflowError
异常。
总之(如此处已经提到的),Python在处理浮点异常时并不一致 - 有时会返回默认值(来自C / pow
/ CPU),有时会引发Python异常。 / p>