f浮动时repr(f),str(f),print(f)的精度 [英] Precision of repr(f), str(f), print(f) when f is float

查看:125
本文介绍了f浮动时repr(f),str(f),print(f)的精度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我跑步:

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

然后pi以16位数字打印,

Then pi is printed with 16 digits,

但是,根据:

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

我的精度是15位数字.

My precision is 15 digits.

所以,我应该依靠该值的最后一位数字(即π的值确实是3.141592653589793nnnnnn).

So, should I rely on the last digit of that value (i.e. that the value of π indeed is 3.141592653589793nnnnnn).

推荐答案

TL; DR

str(float)repr(float)的最后一位数字可能是错误的",因为似乎十进制表示没有正确舍入.

The last digit of str(float) or repr(float) can be "wrong" in that it seems that the decimal representation is not correctly rounded.

>>> 0.100000000000000040123456
0.10000000000000003

但是该值仍然比0.1000000000000000(少1位数字)更接近原始值.

But that value is still closer to the original than 0.1000000000000000 (with 1 digit less) is.

对于math.pi,pi的十进制近似值为3.14159265358979 3238463 ...,在这种情况下,最后一位是正确的.

In the case of math.pi, the decimal approximation of pi is 3.141592653589793238463..., in this case the last digit is right.

sys.float_info.dig告诉您保证始终精确到多少个十进制数字.

The sys.float_info.dig tells how many decimal digits are guaranteed to be always precise.

Python 3.1+(对于repr为2.7)中的str(float)repr(float)的默认输出是转换为float时将返回原始值的最短字符串;如果有歧义,则最后一位四舍五入到最接近的值.浮点数可提供〜15.9的十进制数字精度;但实际上,要明确表示一个53位二进制数,就需要达到17位十进制精度,

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; in case of ambiguity, the last digit is rounded to the closest value. A float provides ~15.9 decimal digits of precision; but actually up to 17 decimal digit precision is required to represent a 53 binary digits unambiguously,

例如,0.100000000000000040x1.999999999999dp-40x1.999999999999cp-4之间,但后者更近.这2个具有十进制扩展名

For example 0.10000000000000004 is between 0x1.999999999999dp-4 and 0x1.999999999999cp-4, but the latter is closer; these 2 have the decimal expansions

0.10000000000000004718447854656915296800434589385986328125

0.100000000000000033306690738754696212708950042724609375

分别.显然后者更加接近,因此选择了二进制表示形式.

respectively. Clearly the latter is closer, so that binary representation is chosen.

现在,当使用str()repr()将它们转换回字符串时,将选择产生完全相同值的最短字符串;这两个值分别是0.100000000000000050.10000000000000003

Now when these are converted back to string with str(), or repr(), the shortest string that yields the exactly same value is chosen; for these 2 values they are 0.10000000000000005 and 0.10000000000000003 respectively

IEEE-754中double的精度为53个二进制数字;以十进制表示,您可以通过以10为底的对数2 ^ 53来计算精度

The precision of a double in IEEE-754 is 53 binary digits; in decimal you can calculate the precision by taking 10-based logarithm of 2^53,

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

表示几乎 16位精度. float_info精度告诉您总是可以表示多少字符,该数字为15,因为有些数字带有16个十进制数字是无法区分的.

meaning almost 16 digits of precision. 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.

但是,这还不是全部.在Python 3.2+内部发生的事情是float.__str__float.__repr__最终调用相同的C方法

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:

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;
}

然后,对于'r'模式(代表repr),PyOS_double_to_string要么调用模式0的_Py_dg_dtoa,它是将双精度型转换为字符串的内部例程,或者使用%17g用于_Py_dg_dtoa无法使用的平台.

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.

snprintf的行为完全取决于平台,但是如果使用_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.

_Py_dg_dtoa模式0 是指定如下:

The _Py_dg_dtoa mode 0 is specified as follows:

0 ==>读入并舍入到最接近值时产生d的最短字符串.

0 ==> shortest string that yields d when read in and rounded to nearest.

所以就是这样-产生的字符串在读入时必须精确地再现double值,并且它必须是可能的最短表示形式,并且在将要读入的多个十进制表示形式中最接近二进制值.现在,这也可能意味着十进制扩展的最后一位数字与以该长度取整的原始值不匹配,只是十进制表示形式尽可能接近原始二进制表示形式.因此就是YMMV.

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. 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.

这篇关于f浮动时repr(f),str(f),print(f)的精度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆