python - python中整数除法的基本含义是什么?
问题描述
我正在运行 python 3.7.3
关于整数除法运算符:“//”(双除法、双正斜杠、双除法运算符?我不确定确切的名称。)
它似乎没有给出一致的结果,而且我发现的许多解释都不能完全解释它的结果。
这里[在Python中有'//'的原因是什么?(和其他地方)据说“//”运算符给出了没有余数的商。好像a // b
是一样的(或者如果是负数floor(a / b)
则四舍五入)。a / b
但是,有时它不会给出这个答案。例如,1 // 0.2
计算结果为 4。但是1 / 0.2
返回 5,math.floor(1 / 2)
也返回 5。它给出的数字比整数除法应该小一。如果将//
10 除以 2,则运算符返回 5,但 1 除以 0.2 不能正常工作。
这个问题出现在其他时候我使用//
运算符来划分浮点数。喜欢5 // 0.2
或100 // 0.2
。我不知道这是否是浮点运算的一些怪癖,但是如果您键入math.floor(5 / 0.2)
(或任何其他给出问题的数字集),这些问题似乎就会消失。除非你除负数,在这种情况下你必须使用math.ceil()
而不是math.floor()
我目前的解决方案是这样的:
import math
def integerDivision(a,b):
tmp = a / b
if tmp > 1:
return(math.floor(tmp))
else:
return(math.ceil(tmp))
//
在某些浮点情况下,运算符的实现是什么使其无法给出正确的结果?//
除了上面的代码,有没有更好的方法来解决运营商的这个问题?
解决方案
这与实施无关。这是关于运算符的语义。无论实施如何,//
操作员都需要为您提供应用于浮点数时看到的结果,并且这些结果确实是正确的(对于浮点数)。如果您不想要这些结果,浮点数可能是您正在做的错误工具。
1 // 0.2
给出浮点数,表示其参数的商的确切值的下限. 但是,右侧参数的值与您输入的值不完全一致。右侧参数的值是 64 位 IEEE 二进制浮点可表示的最接近 0.2 的值,略高于 0.2:
>>> import decimal
>>> decimal.Decimal(0.2)
Decimal('0.200000000000000011102230246251565404236316680908203125')
因此,商的确切值略小于 5,因此1 // 0.2
给出了4.0
.
1 / 0.2
给你,5.0
因为商的确切值不能表示为浮点数。结果需要四舍五入,并四舍五入为5.0
。//
不执行此舍入;它计算精确值的下限,而不是舍入浮点数的下限。(结果//
可能需要四舍五入,但这是不同的四舍五入。)
尽管如此,实现需要比 更复杂floor(x / y)
,因为那样会给出错误的结果。CPython//
的浮点实现基于fmod
. 您可以Objects/floatobject.c
在 CPython 源代码库中查看实现。
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 approximation; the 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 platforms; ensure
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);
}
static PyObject *
float_floor_div(PyObject *v, PyObject *w)
{
PyObject *t, *r;
t = float_divmod(v, w);
if (t == NULL || t == Py_NotImplemented)
return t;
assert(PyTuple_CheckExact(t));
r = PyTuple_GET_ITEM(t, 0);
Py_INCREF(r);
Py_DECREF(t);
return r;
}
其他参数类型将使用其他实现,具体取决于类型。
推荐阅读
- passwords - 从检查元素隐藏密码字段值?
- javascript - 打字稿使用地图或对象
- perl - 如何在 perl 中同时使用 Time::Local 和 Time::localtime
- c# - 如何从 C# 代码中将 Visual Studio 文件类型图标作为位图获取
- python - 无法将 MQTTUtils 导入 Python 项目
- c++ - 如何在 C++ 中打印原始 std::string/c 样式的字符串
- sharepoint - 在 SharePoint 工作流中的 10 月和 11 月时间范围内添加月份时,为什么添加月份计算不正确?
- php - 如何重新启动 php while 循环
- html - 加载关于:包含 URL 内容的空白页面
- c++ - 需要有关如何将我的随机数数组连接到冒泡排序的帮助