Python中3 // .1为何等于29而非30?使用//需注意什么?
问题原因解析
首先要明确:0.1这类十进制小数无法用二进制浮点数精确存储,Python里的.1实际是一个略大于数学意义上0.1的近似值。这是所有基于IEEE 754标准的编程语言都会遇到的浮点数精度问题。
三个运算的差异
floor(3 / .1) == 30:
3除以这个近似的.1,得到的结果是一个极其接近30但略小于30的数(用高精度格式打印会显示为29.999999999999996)。但由于浮点数的精度限制,这个值在Python中会被“归一化”为30.0,所以floor()函数返回30。int(3 / .1) == 30:int()函数对于正数会直接截断小数部分,同样因为上述的归一化,3 / .1被当作30.0处理,截断后得到30。3 // .1 == 29://运算符的逻辑不是先计算3/.1再取整,而是直接寻找最大的整数n,使得n * .1 <= 3。由于.1是略大于0.1的近似值,30 * .1的实际结果会略大于3(约3.0000000000000004),不满足<=3的条件;而29 * .1的结果约为2.9000000000000004,满足条件,因此//返回29.0。
使用//运算符的注意点
- 当操作数是浮点数时,
//的行为和int(x/y)、floor(x/y)并不完全等价,核心原因是浮点数的精度误差会影响//的判断逻辑。 - 如果需要精确的整数除法,建议先将浮点数转换为精确的十进制类型(比如Python的
decimal.Decimal),再进行运算,避免精度问题。 - 对于涉及
.1、.01这类无法精确表示的小数运算,一定要警惕浮点数误差带来的异常结果。
内容的提问来源于stack exchange,提问作者Albert Chung
相关产品推荐
相关产品推荐

