简体   繁体   English

当 f 为浮点数时 repr(f)、str(f)、print(f) 的精度

[英]Precision of repr(f), str(f), print(f) when f is float

If I run:如果我运行:

>>> import math
>>> print(math.pi)
3.141592653589793

Then pi is printed with 16 digits,然后用16位数字打印pi,

However, according to:然而,根据:

>>> import sys
>>> sys.float_info.dig 
15

My precision is 15 digits.我的精度是 15 位数字。

So, should I rely on the last digit of that value (ie that the value of π indeed is 3.141592653589793nnnnnn).所以,我应该依赖该值的最后一位数字(即 π 的值确实是 3.141592653589793nnnnnn)。

TL;DR TL; 博士

The last digit of str(float) or repr(float) can be "wrong" in that it seems that the decimal representation is not correctly rounded. str(float)repr(float)的最后一位数字可能是“错误的”,因为十进制表示似乎没有正确舍入。

>>> 0.100000000000000040123456
0.10000000000000003

But that value is still closer to the original than 0.1000000000000000 (with 1 digit less) is.但该值仍比0.1000000000000000 (少 1 位数)更接近原始值。

In the case of math.pi , the decimal approximation of pi is 3.14159265358979 3238463 ..., in this case the last digit is right.math.pi的情况下, math.pi的十进制近似值是 3.14159265358979 3238463 ...,在这种情况下,最后一位数字是正确的。

The sys.float_info.dig tells how many decimal digits are guaranteed to be always precise. sys.float_info.dig告诉有多少十进制数字保证总是精确的。


The default output for both str(float) and repr(float) in Python 3.1+ (and 2.7 for repr ) is the shortest string that when converted to float will return the original value;两者的默认输出str(float)repr(float)在Python 3.1+(和2.7 repr )是最短的字符串,当转换为float将返回原来的值; in case of ambiguity, the last digit is rounded to the closest value.如果出现歧义,最后一位数字将四舍五入为最接近的值。 A float provides ~15.9 decimal digits of precision;浮点数提供约 15.9 位十进制数的精度; but actually up to 17 decimal digit precision is required to represent a 53 binary digits unambiguously,但实际上最多需要 17 个十进制数字精度才能明确表示 53 个二进制数字,

For example 0.10000000000000004 is between 0x1.999999999999dp-4 and 0x1.999999999999cp-4 , but the latter is closer;例如0.10000000000000004介于0x1.999999999999dp-40x1.999999999999cp-4 ,但后者更接近; these 2 have the decimal expansions这两个有十进制扩展

0.10000000000000004718447854656915296800434589385986328125

and

0.100000000000000033306690738754696212708950042724609375

respectively.分别。 Clearly the latter is closer, so that binary representation is chosen.显然后者更接近,因此选择了二进制表示。

Now when these are converted back to string with str() , or repr() , the shortest string that yields the exactly same value is chosen;现在,当使用str()repr()将它们转换回字符串时,会选择产生完全相同值的最短字符串; for these 2 values they are 0.10000000000000005 and 0.10000000000000003 respectively对于这两个值,它们分别是0.100000000000000050.10000000000000003


The precision of a double in IEEE-754 is 53 binary digits; IEEE-754 中double的精度是 53 个二进制数字; in decimal you can calculate the precision by taking 10-based logarithm of 2^53,在十进制中,您可以通过采用 2^53 的基于 10 的对数来计算精度,

>>> math.log(2 ** 53, 10)
15.954589770191001

meaning almost 16 digits of precision.意味着几乎16 位的精度。 The float_info precision tells how much you can always expect to be presentable, and this number is 15, for there are some numbers with 16 decimal digits that are indistinguishable. float_info精度告诉您始终可以期望呈现多少,这个数字是 15,因为有些数字是无法区分的 16 位十进制数字。


However this is not the whole story.然而,这并不是故事的全部。 Internally what happens in Python 3.2+ is that the float.__str__ and float.__repr__ end up calling the same C method float_repr :在 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;
}

The PyOS_double_to_string then, for the 'r' mode (standing for repr), calls either the _Py_dg_dtoa with mode 0, which is an internal routine to convert the double to a string, or snprintf with %17g for those platforms for which the _Py_dg_dtoa wouldn't work.PyOS_double_to_string那么,对于'r'模式(静置再版),呼叫任一_Py_dg_dtoa用模式0,这是一个内部程序来双重转换为字符串,或snprintf%17g这些平台的量, _Py_dg_dtoa止跌不行。

The behaviour snprintf is entirely platform dependent, but if _Py_dg_dtoa is used (as far as I understand, it should be used on most machines), it should be predictable. snprintf 的行为完全依赖于平台,但如果使用_Py_dg_dtoa (据我所知,它应该在大多数机器上使用),它应该是可预测的。

The _Py_dg_dtoa mode 0 is specified as follows: _Py_dg_dtoa mode 0指定如下:

0 ==> shortest string that yields d when read in and rounded to nearest. 0 ==> 读入时产生 d 并四舍五入到最接近的最短字符串。

So, that is what happens - the yielded string must exactly reproduce the double value when read in, and it must be the shortest representation possible, and among multiple decimal representations that would be read in, it would be the one that is closest to the binary value.所以,这就是发生的事情——在读入时,产生的字符串必须准确地重现double值,并且它必须是可能的最短表示,并且在将被读入的多个十进制表示中,它是最接近于二进制值。 Now, this might also mean that the last digit of decimal expansion does not match the original value rounded at that length, only that the decimal representation is as close to the original binary representation as possible.现在,这也可能意味着十进制扩展的最后一位与按该长度舍入的原始值匹配,只是十进制表示尽可能接近原始二进制表示。 Thus YMMV.因此YMMV。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM