格式化浮点数时的Python格式默认舍入

2022-01-15 00:00:00 python floating-point format numbers

问题描述

我正在尝试在 Python 2.7.10 中解决我的代码中的一些浮点问题.在测试时,我遇到了 format 方法的奇怪行为:

I'm trying to solve some floating-point problems in my code in Python 2.7.10. When testing I've encountered a strange behaviour with the format method:

print "{}".format(0.3000000000004) # 13 decimals

打印:0.3

但是:

print "{}".format(0.300000000004) # 12 decimals

打印:0.300000000004

既然我没有指定格式,为什么它会四舍五入第一个数字?是否有默认允许的小数位数?

Since I'm not specifying the format, why does it round the first number? Is there a default number of allowed decimal places?


解决方案

由于没有指定格式,所以使用默认类型强制转换为字符串.所以这不是 format 的真正问题.Python 2 将 float.__str__ 截断到 12 个字符的精度(不包括前导零,如果有的话),并且在这种情况下截断后,所有尾随零都被清除:

Since you do not specify a format, the default type coercion to string is used. So this isn't really an issue with format. Python 2 truncates to a precision of 12 characters (excluding the leading zero, if any) for float.__str__, and after truncation in this case, all trailing zeros are cleaned up:

>>> str(0.3000000000004) # unlike str(0.3000000000014) -> '0.300000000001'
'0.3'

添加 format_spec :f 为您提供默认精度 6:

Adding the format_spec :f gives you the default precision of 6:

>>> '{:f}'.format(0.3000000000004)
'0.300000' 

指定宽度和精度或使用 repr 以获得良好的表示:

Specify the width and precision or use repr to get a good representation:

>>> '{!r}'.format(0.3000000000004)
'0.3000000000004'

但在 Python 3 中的行为有所不同:

The behavior is different in Python 3 though:

>>> str(0.3000000000004)
'0.3000000000004'

<小时>

浮点数的格式仅由一个函数处理float_repr(它没有特殊的 float_str 函数):

(reprfunc)float_repr,                       /* tp_repr */
...
(reprfunc)float_repr,                        /* tp_str */

而 Python2.7 定义了一个单独的处理程序 float_strfloat_repr 分别代表 __str____repr__:

whereas Python2.7 defines a separate handler float_str and float_repr for __str__ and __repr__ respectively:

(reprfunc)float_repr,                       /* tp_repr */
...
(reprfunc)float_str,                        /* tp_str */

我认为这里的决定性变量是超过 12d.p 的精度损失的原因.是 PyFloat_STR_PRECISION(在 Python 2 中定义):

The deciding variable here which I think is the reason for the precision loss beyond 12d.p. is PyFloat_STR_PRECISION (defined in Python 2):

#define PyFloat_STR_PRECISION 12

对于在默认转换中超过 12 个字符的浮点数,它会反转为截断.

It reverses to a truncation for floats taking more than 12 characters in the default conversion.

相关文章