int(ceil(x))是否表现良好?

时间:2013-12-12 19:30:44

标签: python math floating-point

如果我有一个浮点数x,它在[0,10 6 ]的范围内,那么在Python中是否可以保证int(ceil(x))将被正确地舍入?

似乎有可能从我知道的很少,ceil可能会向下舍入导致不正确的结果。类似于:x = 7.6,ceil(x)= 7.999 ..,int(ceil(x))= 7。会发生这种情况吗?

4 个答案:

答案 0 :(得分:6)

正确实现的ceil返回ceil( x )的确切数学值,没有错误。当使用IEEE 754或任何合理的浮点系统时,ceil不会出现舍入错误。

这不能防止来自ceil功能以外的来源的不利影响。例如,ceil(1.000000000000000000000000000000001)将返回1,因为1.000000000000000000000000000000001在调用ceil之前转换为浮点值,并且该转换将其结果舍入。同样,从doublefloat的转换以及对ceil的调用可能会产生一个不是原始double值的上限的值。

当然,ceilint的结果转换依赖于int的范围。只要该值在范围内,转换就不应更改该值。

答案 1 :(得分:3)

Python对float的浮点格式的保证不是很严格。我认为它只是说它使用了double,而在CPython的情况下,它就是C编译器调用的double

对于高达一百万的数字,你很好。实际使用中没有浮点格式会丢失小的整数精度。 C标准要求double最多10位十进制数。

您可能观察到的是,由于浮点舍入int(sum([1.1] * 10))为10而不是11.这是因为sum([1.1] * 10)10.999999999999998,而不是11.0。< / p>

ceil的结果总是一个整数,所以它永远不会被int向下舍入(或者如果你喜欢它将向下舍入,但这样做不会改变它的值!)

答案 2 :(得分:1)

如果您需要有关python&#39; float的信息,请检查sys.float_info功能。特别是它的文档清楚地表明python float的行为与C float / double完全相同,并提供相同的保证。事实上它链接到C&C标准的this部分。

所以python的保证与C的双重保证相同。如果一个整数可以完全表示为float,那么int(the_float)将返回正确的整数。 问题是,对于足够大的float s,并非所有整数都可以准确表示。

Rob的例子:

int(math.ceil(18014398509481985.5)) => 18014398509481984

<{1}}或int失败,而只是ceil 的事实:

18014398509481985.5

总结:如果>>> 18014398509481985.5 1.8014398509481984e+16 的上限可以准确表示,那么x 返回正确的整数。否则int(ceil(x))将返回int(x)返回的整数,该整数不必是ceil(x)&#34;的数学上限。

目前,几乎所有计算机都符合IEEE 754标准,因此您可以确保x根据标准返回正确的结果。

在嵌入式系统中,这可能不是真的,但我不确定python是否可以在不符合IEEE 754标准的架构上运行。


如果您不相信我们可以说的话,您可以随时尝试阅读int(ceil(x))PyLong_FromDouble的源代码:

Objects/longobject.c

代码不是简单的转换,因为长整数不表示为C双精度。似乎即使在python2中也没有PyObject * PyLong_FromDouble(double dval) { PyLongObject *v; double frac; int i, ndig, expo, neg; neg = 0; if (Py_IS_INFINITY(dval)) { PyErr_SetString(PyExc_OverflowError, "cannot convert float infinity to integer"); return NULL; } if (Py_IS_NAN(dval)) { PyErr_SetString(PyExc_ValueError, "cannot convert float NaN to integer"); return NULL; } if (dval < 0.0) { neg = 1; dval = -dval; } frac = frexp(dval, &expo); /* dval = frac*2**expo; 0.0 <= frac < 1.0 */ if (expo <= 0) return PyLong_FromLong(0L); ndig = (expo-1) / PyLong_SHIFT + 1; /* Number of 'digits' in result */ v = _PyLong_New(ndig); if (v == NULL) return NULL; frac = ldexp(frac, (expo-1) % PyLong_SHIFT + 1); for (i = ndig; --i >= 0; ) { digit bits = (digit)frac; v->ob_digit[i] = bits; frac = frac - (double)bits; frac = ldexp(frac, PyLong_SHIFT); } if (neg) Py_SIZE(v) = -(Py_SIZE(v)); return (PyObject *)v; }

答案 3 :(得分:0)

通常情况是浮点数存在舍入误差,但这只是因为并非所有以十进制表示的数字都能完美地用二进制表示。那些可以准确表示的数字将不会应用任何舍入。对于最大为2 ** 53的整数值就是这种情况,所以只有6位数就可以安全。

无法在float中准确表示的最低正整数值是9007199254740993.