我希望3/2等于2而不是1.5。
我知道有一个数学术语可以描述这个操作(不是四舍五入),但我现在想不起来了。无论如何,我怎样才能在不使用两个函数的情况下完成这个操作?
以下是我不想要的示例:
answer = 3/2 then math.ceil(answer)=2 (why does math.ceil(3/2)=1?)
ex of what I DO want:
"function"(3/2) = 2
我希望3/2等于2而不是1.5。
我知道有一个数学术语可以描述这个操作(不是四舍五入),但我现在想不起来了。无论如何,我怎样才能在不使用两个函数的情况下完成这个操作?
以下是我不想要的示例:
answer = 3/2 then math.ceil(answer)=2 (why does math.ceil(3/2)=1?)
ex of what I DO want:
"function"(3/2) = 2
Python只提供了两种类型的除法本地运算符:"真"除法和"向下舍入"除法。因此,你想要的不是一个单独的函数。然而,使用一些简短的表达式可以轻松实现多种不同类型的带有舍入的除法。
根据标题的要求:给定严格的整数输入,“向上舍入”除法可以使用(a+(-a%b))//b
来实现,“远离零”除法可以使用更复杂的a//b if a*b<0 else (a+(-a%b))//b
来实现。其中之一可能是你想要的。至于为什么...
为了给出更详细的答案...
首先,让我回答一下有关为什么 3/2==1
和 math.ceil(3/2)==1.0
的子问题,以解释 Python 除法运算符的工作方式。这里有两个主要问题...
float
vs int
division: 在 Python 2 中,除法的行为取决于输入的类型。如果 a
和 b
都是整数,则 a/b
执行“向下取整”或“地板整数”除法(例如 3/2==1
,但 -3/2==-2
)。这等效于 int(math.floor(float(a)/b))
。
但是,如果 a
和 b
中至少有一个是浮点数,则 Python 执行“真实”除法,并给出一个 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版本中的行为相同。 同样,我假设如果b
是正数,则0<=a%b<b
,如果b
是负数,则b<=a%b<=0
。 这是Python的行为,但其他语言可能具有略有不同的模数运算符。
带有四舍五入的四种基本整数除法类型:
"round down" 也称为 "向下取整" 或 "负无穷大取整" 的除法: Python 可以通过 a//b
实现这一功能。
"round up" 也称为 "向上取整" 或 "正无穷大取整" 的除法: 可以通过 int(math.ceil(float(a)/b))
或 (a+(-a%b))//b
实现。后者的原因是,如果 a
是 b
的倍数,则 -a%b
为 0,否则它是我们需要添加到 a
中的数量,以达到下一个最高的倍数。
"round towards zero" 也称为 "截断取整" 的除法 - 可以通过 int(float(a)/b)
实现。如果不使用浮点数进行计算,则更加棘手...因为 Python 仅提供向下取整的整数除法,而 %
运算符具有类似的向下取整偏差,我们没有任何非浮点运算符可以在 0 周围对称地进行取整。因此,我能想到的唯一方法就是将向下取整和向上取整构造成分段表达式:a//b if a*b>0 else (a+(-a%b))//b
。
"round away from zero" 也称为 "远离零取整" 的除法 - 不幸的是,这比截断取整还要棘手。我们无法利用 int
运算符的截断行为,因此即使包括浮点运算符,我也想不出一个简单的表达式。因此,我必须使用截断取整表达式的反向操作,并使用 a//b if a*b<0 else (a+(-a%b))//b
。
(a+b-1)//b
提供了比上述任何解决方案更有效的向上/远离零的四舍五入,但对于负数则无效。(a // b)+1
怎么样? - Devy(a // b)+1
对于b的倍数返回错误的值--例如,(10//5)+1
返回3,而不是2。 - Eli Collins该帖子的意图是"如何在Python中实现向正无穷取整的除法"(建议您更改标题)。
根据IEEE-754标准(请阅读这个概述),这是一种完全合法的舍入模式,称为"向正无穷取整"(或"远离零取整")。大多数9个反对票都是不公平地攻击楼主。是的,在本地Python中没有单函数方法来实现这一点,但我们可以使用round(float(a)/b)
,或者子类化numbers.Number
并重写__div__()
。
楼主需要澄清他们是否希望-3/2向-2或-1取整(或者对于负操作数不关心)。由于他们已经说过他们不想向上取整,我们可以推断-3/2应该向-2取整。
足够的理论。对于实现:
round(float(a)/b)
math.ceil(float(a)/b)
会向上取整,而你说你不想要这个
但是,如果这是你默认的除法操作,或者你经常需要这样做,那么可以像下面的伪代码一样做:从numbers.Number
的子类Real、Rational或Integral中继承(2.6版中新增),重新定义 __div__()
或者定义一个非默认的替代 __divra__()
操作。你可以定义一个类成员或者类方法 rounding_mode
并在除法运算中查找它。但是要注意 __rdiv__()
和普通浮点数混合使用的问题。
.
import numbers
class NumberWithRounding(numbers.Integral):
# Here you could implement a classmethod setRoundingMode() or member rounding_mode
def __div__(self,other):
# here you could consider value of rounding_mode, or else hardwire it like:
return round(float(self)/other)
# You also have to raise ImplementationError/ pass/ or implement the other 31
# methods for Float: __abs__(),...,__xor__() Just shortcut that for now...
Python 3 中的整数除法:
3 // 2 == 1
Python 3 中的非整数除法:
3 / 2 == 1.5
你所说的并不是一种完全的除法。
3/2 -> 1
,3.0/2 -> 1.5
,3.0//2 -> 1.0
。 - user1663903 / 2
等于 1
,而不是 1.5
。当你从除法中得到对于(普通或长)整数除法,结果是一个整数。结果总是向负无穷大舍入:1/2 是 0,(-1)/2 是 -1,1/(-2) 是 -1,(-1)/(-2) 是 0。请注意,如果任何操作数是长整型,则结果是长整型,无论其数值如何。
1
后,就没有办法将其变成 2
。1.5
,你需要使用浮点数除法:3.0 / 2
。math.ceil
来获得 2
。math.ceil
。math.ceil(3.0/2.0)
# or
math.ceil(float(3)/float(2))
你也可以使用“from future”进行导入:
from __future__ import division
math.ceil(3/2) # == 2
但如果你这样做,想要得到整数除法的当前行为,你需要使用双斜杠:
3 // 2 == 1 # True
在gmpy2中,可以进行向上取整(+Inf),向下取整(-Inf)和截断(到0)的整数除法。
>>> gmpy2.c_div(3,2)
mpz(2)
>>> help(gmpy2.c_div)
Help on built-in function c_div in module gmpy2:
c_div(...)
c_div(x,y): returns the quotient of x divided by y. The quotient
is rounded towards +Inf (ceiling rounding). x and y must be integers.
>>> help(gmpy2.f_div)
Help on built-in function f_div in module gmpy2:
f_div(...)
f_div(x,y): returns the quotient of x divided by y. The quotient
is rounded towards -Inf (floor rounding). x and y must be integers.
>>> help(gmpy2.t_div)
Help on built-in function t_div in module gmpy2:
t_div(...)
t_div(x,y): returns the quotient of x divided by y. The quotient
is rounded towards 0. x and y must be integers.
>>>
gmpy2 可在 http://code.google.com/p/gmpy/ 获取。
(免责声明:我是 gmpy 和 gmpy2 的当前维护者。)
from __future__ import division
f(3/2)==2
和 f(1.4)==2
,那么您需要让 f
为 math.trunc(math.ceil(x))
。math.trunc(x + 0.5)
。这样,f(3/2)==2
并且 f(1.4)==1
。
math.ceil(3/2) = 1
因为3/2 = 1
(整数除法),所以你将1进行了向上取整,而不是1.5。 - NullUserException