我希望3/2等于2而不是1.5
我知道该操作有一个数学术语(不称为舍入),但是我现在不记得它了。
无论如何,我该怎么做而不必执行两个功能?
我不想要的东西:
answer = 3/2 then math.ceil(answer)=2 (why does math.ceil(3/2)=1?)
我想要的东西前:
"function"(3/2) = 2
最佳答案
简短回答...
Python仅为两种类型的除法提供 native 运算符:“真”除法和“舍入”除法。因此,您所需的功能无法作为一个单一功能使用。但是,可以使用一些短表达式轻松实现许多不同类型的舍入除法。
根据标题的要求:给定严格的整数输入,可以使用(a+(-a%b))//b
实现“舍入”除法,而可以使用更复杂的a//b if a*b<0 else (a+(-a%b))//b
实现“从零舍入”除法。其中之一可能就是您想要的。至于为什么...
要给出更长的答案...
首先,让我通过解释Python除法运算符的工作方式回答有关3/2==1
和math.ceil(3/2)==1.0
的子问题。有两个主要问题在起作用...
float
与int
划分:在Python 2下,划分的行为取决于输入类型。如果a
和b
都是整数,则a/b
执行“舍入”或“底整数”除法(例如3/2==1
,但-3/2==-2
)。这等效于int(math.floor(float(a)/b))
。
但是,如果a
和b
中至少有一个是浮点数,Python将执行“true”除法,并为您提供float
结果(例如3.0/2==1.5
和-3.0/2==-1.5
)。这就是为什么有时会看到float(a)/b
构造的原因:即使两个输入都是整数(例如float(3)/2==1.5
),它也被用于强制进行真除法。这就是为什么示例math.ceil(3/2)
返回1.0
,而math.ceil(float(3)/2)
返回2.0
的原因。结果已经四舍五入,甚至没有达到math.ceil()
。
默认为“真除法” :2001年,决定(PEP 238)应该更改Python的除法运算符,以便始终执行“真”除法,而不管输入是浮点数还是整数(例如,这样做3/2==1.5
)。为了不破坏现有脚本,将默认行为的更改推迟到Python 3.0之前进行;为了在Python 2.x下获得此行为,您必须通过在文件顶部添加from __future__ import division
来按文件启用它。否则,将使用旧的类型相关行为。
但是仍然经常需要“向下舍入”划分,因此PEP并没有完全做到这一点。相反,它引入了一个新的除法运算符:a//b
,即使输入包含浮点数,该运算符也始终执行舍入除法。在Python 2.2+和3.x下都可以使用它而无需做任何特殊的事情。
这样一来,舍入取整:
为了简化操作,下面的表达式在处理整数时都使用a//b
运算符,因为它在所有python版本中的行为都相同。同样,我假设如果0<=a%b<b
为正,则为b
,如果b为负,则为b<=a%b<=0
。这就是Python的行为方式,但其他语言的模运算符可能略有不同。
舍入的整数除法的四种基本类型:
a//b
原生提供此功能。 int(math.ceil(float(a)/b))
或(a+(-a%b))//b
实现。后一个方程之所以有效,是因为如果-a%b
是a
的倍数,则b
为0;否则,我们需要将其添加到a
才能达到下一个最高倍数。 int(float(a)/b)
实现。在不使用浮点数的情况下执行此操作比较棘手...由于Python仅提供向下舍入的整数除法,并且%
运算符具有类似的向下舍入偏差,因此我们没有任何非浮点运算符,它们对称地在0左右舍入因此,我唯一想到的方法是从上舍入和下舍入构造一个分段表达式:a//b if a*b>0 else (a+(-a%b))//b
。 int
运算符的截断行为了,因此即使包含浮点运算,我也无法想到一个简单的表达式。因此,我必须将舍入到零的表达式取反,并使用a//b if a*b<0 else (a+(-a%b))//b
。 请注意,如果您仅使用正整数,则
(a+b-1)//b
会比上述任何一种解决方案更有效地提供四舍五入/远离零的功能,但会导致负数的产生。希望对您有帮助...并且乐于进行编辑,如果有人可以提出更好的方程,说明从零舍入/舍入为零。我发现我特别不满意的那些。
关于python - 如何在Python中使用Round-towards-Infinity实现除法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7181757/