python 如何判断整除?

Python023

python 如何判断整除?,第1张

题:如何判断一个数能否被3整除?(或者被其他任意一个数整除)

方法一:取余

x = input("input an number:")

if x % 3 == 0:    

print "%d 能被3整除" %(x)  

else:  

print "%d 不能被3整除" %(x)12345

方法二:还有一种就是将其各个数位上的数字相加,然后除以3,如果能被3整除,则原数字能被3整除。

x = 0

y = raw_input("input an number:") #这里取为字符串的原因是,要遍历数字的各个数位

for i in y:      

print int(i)

x = x + int(i)  #将数字的各个数位上的数字加起来

print x

if x % 3 == 0:

print "%s 能被3整除" %(y)

else:      

print "%s 不能被3整除" %(y)1234567891011

先说结论:这个问题是由于cpython的地板除运算符(//)的实现不是 浮点除法+floor 来实现而是用了(被除数 - 余数)/除数 导致的。

PS:Jython下可以得到20.0,而PEP里规定了a // b应该等于round(a/b),所以似乎这是cpython实现的一个bug?

首先先分析下1 / 0.05究竟应该等于多少。答案就是精确的20.0。

简单解释下:IEEE754浮点数规定,如果一个浮点数的值不能被精确记录,那么它的值会被记成与这个数距离最近的可以被IEEE浮点数表示的数。

首先,0.05在二进制下是无限循环小数,自然不能被精确记录,因此0.05这个浮点数的实际值是不等于0.05的,实际值是约为0.05 + 2.7e-18。

之后做浮点除法,实际上做的是1 / (0.05+2.7...e-18),这个除法的结果大约是20 - 1.1e-15。这个值也不能被精确表示,恰好离这个数最近的可以表示的值就是20.0,因此即使有浮点数误差结果也是精确的20.0。

既然1/0.05就是20.0,那么对他做floor运算自然也是20了。

现在的问题就是为什么1 // 0.05会变成19.0,要解决这个问题只能翻源码看//运算符的实现。

直接把cpython/floatobject.c at 829b49cbd2e4b1d573470da79ca844b730120f3d · python/cpython · GitHub 中实现//运算的一段贴上来:

static PyObject *

float_divmod(PyObject *v, PyObject *w)

{

double vx, wx

double div, mod, floordiv

CONVERT_TO_DOUBLE(v, vx)

CONVERT_TO_DOUBLE(w, wx)

if (wx == 0.0) {

PyErr_SetString(PyExc_ZeroDivisionError, "float divmod()")

return NULL

}

PyFPE_START_PROTECT("divmod", return 0)

mod = fmod(vx, wx)

/* fmod is typically exact, so vx-mod is *mathematically* an

exact multiple of wx. But this is fp arithmetic, and fp

vx - mod is an approximationthe result is that div may

not be an exact integral value after the division, although

it will always be very close to one.

*/

div = (vx - mod) / wx

if (mod) {

/* ensure the remainder has the same sign as the denominator */

if ((wx <0) != (mod <0)) {

mod += wx

div -= 1.0

}

}

else {

/* the remainder is zero, and in the presence of signed zeroes

fmod returns different results across platformsensure

it has the same sign as the denominator. */

mod = copysign(0.0, wx)

}

/* snap quotient to nearest integral value */

if (div) {

floordiv = floor(div)

if (div - floordiv >0.5)

floordiv += 1.0

}

else {

/* div is zero - get the same sign as the true quotient */

floordiv = copysign(0.0, vx / wx)/* zero w/ sign of vx/wx */

}

PyFPE_END_PROTECT(floordiv)

return Py_BuildValue("(dd)", floordiv, mod)

}

可以发现cpython中x // y的实现实际上是

round((x - fmod(x, y)) / y)

,其中fmod函数是求两个浮点数相除的余数。

这样一来就解释的通了:在十进制下,显然1除以0.05的余数应该是0.0。然而在IEEE浮点数环境中,0.05的实际值是约0.05 + 2.7e-18,略大于0.05,这样一来1除以这个数的余数就成了约0.05 - 5e-17,从1中减掉这么多之后就只剩0.95了,除以0.05再round后变成19.0。