Die*_*rin 5 python floating-point-precision
如果我跑:
>>> import math
>>> print(math.pi)
3.141592653589793
Run Code Online (Sandbox Code Playgroud)
然后pi打印16位数,
但是,根据:
>>> import sys
>>> sys.float_info.dig
15
Run Code Online (Sandbox Code Playgroud)
我的精度是15位数.
那么,我应该依赖该值的最后一位(即π的值确实是3.141592653589793nnnnnn).
Ant*_*ala 14
TL; DR
最后一个数字str(float)或者repr(float)可能是"错误的",因为似乎十进制表示没有正确舍入.
>>> 0.100000000000000040123456
0.10000000000000003
Run Code Online (Sandbox Code Playgroud)
但是这个值仍然接近原始值0.1000000000000000(少了1位数).
在这种情况下math.pi,pi的十进制近似是3.14159265358979 3238463 ...,在这种情况下,最后一位是正确的.
在sys.float_info.dig讲述许多十进制数字是如何保证是始终精确.
默认的输出两者str(float)并repr(float)在Python 3.1+(和2.7 repr)是当转换为最短的字符串float将返回原始值; 在模糊的情况下,最后一个数字四舍五入到最接近的值.float提供~15.9十进制数字的精度; 但实际上需要高达17位十进制数的精度才能明确表示53位二进制数字,
例如0.10000000000000004介于0x1.999999999999dp-4和之间0x1.999999999999cp-4,但后者更接近; 这两个有小数扩展
0.10000000000000004718447854656915296800434589385986328125
Run Code Online (Sandbox Code Playgroud)
和
0.100000000000000033306690738754696212708950042724609375
Run Code Online (Sandbox Code Playgroud)
分别.显然后者更接近,因此选择二进制表示.
现在当这些转换回字符串时str(),或者repr(),选择产生完全相同值的最短字符串; 这些2个值它们0.10000000000000005和0.10000000000000003分别
doubleIEEE-754 中a的精度为53位二进制数字; 在十进制中,您可以通过采用10 ^对数2 ^ 53来计算精度,
>>> math.log(2 ** 53, 10)
15.954589770191001
Run Code Online (Sandbox Code Playgroud)
意思是近 16位数的精度.该float_info精密告诉你多少总是可以期望得到像样,这个数字是15,因为有一些数字与16个十进制数字是无法区分.
然而,这不是全部.在内部,Python 3.2+中发生的事情是,float.__str__并float.__repr__最终调用相同的C方法float_repr:
float_repr(PyFloatObject *v)
{
PyObject *result;
char *buf;
buf = PyOS_double_to_string(PyFloat_AS_DOUBLE(v),
'r', 0,
Py_DTSF_ADD_DOT_0,
NULL);
if (!buf)
return PyErr_NoMemory();
result = _PyUnicode_FromASCII(buf, strlen(buf));
PyMem_Free(buf);
return result;
}
Run Code Online (Sandbox Code Playgroud)
在PyOS_double_to_string那以后,在'r'模式(代表再版),要求无论是_Py_dg_dtoa与模式0,这是一个内部程序的双重转换为字符串,或snprintf与%17g这些平台对于其_Py_dg_dtoa是行不通的.
行为snprintf完全取决于平台,但如果_Py_dg_dtoa使用(据我所知,它应该在大多数机器上使用),它应该是可预测的.
在_Py_dg_dtoa模式0被指定为如下:
0 ==>最短字符串,在读入时产生d并舍入到最接近.
所以,这就是发生的事情 - 生成的字符串必须double在读入时精确地再现该值,并且它必须是可能的最短表示,并且在将被读入的多个十进制表示中,它将是最接近二进制的那个值.现在,这也可能意味着十进制扩展的最后一位数与该长度的四舍五入的原始值不匹配,只是十进制表示尽可能接近原始二进制表示.因此YMMV.
| 归档时间: |
|
| 查看次数: |
868 次 |
| 最近记录: |