25

是否有一种简单的 Pythonic 方法可以在不使用浮点的情况下舍入到最接近的整数?我想做以下但使用整数算术:

skip = int(round(1.0 * total / surplus))

===============

@John:浮点不能跨平台重现。如果您希望您的代码在不同平台上通过测试,那么您需要避免使用浮点(或在您的测试中添加一些 hacky espilon 的东西并希望它有效)。以上可能很简单,在大多数/所有平台上都是相同的,但我宁愿不做出这样的决定,因为完全避免浮点更容易。那“不符合 Python 的精神”是怎么回事?

4

6 回答 6

42

你可以很简单地做到这一点:

(n + d // 2) // d,其中n是被除数,d是除数。

在最近的 CPython 中,类似(((n << 1) // d) + 1) >> 1或等效的替代方案可能会更慢,其中 an的实现方式与旧的.(((n * 2) // d) + 1) // 2intlong

简单的方法进行 3 次变量访问、1 次常量加载和 3 次整数运算。复杂的方法进行 2 次变量访问、3 次常量加载和 4 次整数运算。整数运算可能需要时间,这取决于所涉及数字的大小。函数局部变量的变量访问不涉及“查找”。

如果您真的对速度感到绝望,请进行基准测试。否则,亲吻。

于 2010-10-16T21:53:55.390 回答
7
skip = (((total << 1) // surplus) + 1) >> 1

左移一位有效地乘以二,右移一位除以二四舍五入。如果结果超过小数点 0.5 部分,则在中间添加一个使得“向下舍入”实际上是向上舍入。

基本上和你写的一样...

skip = int((1.0*total/surplus) + 0.5)

除了所有的东西都乘以 2,然后再除以 2,这是你可以用整数算术做的事情(因为位移不需要浮点)。

于 2010-10-16T19:18:18.880 回答
6

受到zhmyh的回答的启发,即

q, r = divmod(total, surplus)
skip = q + int(bool(r)) # rounds to next greater integer (always ceiling)

,我想出了以下解决方案:

q, r = divmod(total, surplus) 
skip = q + int(2 * r >= surplus) # rounds to nearest integer (floor or ceiling)

由于 OP 要求四舍五入到最接近的整数,因此 zhmhs 的解决方案实际上有点不正确,因为它总是四舍五入到下一个更大的整数,而我的解决方案按要求工作。

(如果您觉得我的回答最好是对 zhmh 的回答进行编辑或评论,让我指出我建议的编辑被拒绝了,因为它最好是评论,但我还没有足够的声誉评论!)

如果您想知道如何divmod定义:根据其文档

对于整数,结果与 相同(a // b, a % b)

因此,我们按照 OP 的要求坚持使用整数算术。

于 2014-04-08T15:35:35.647 回答
2

还有一个有趣的方法:

q, r = divmod(total, surplus)
skip = q + int(bool(r))
于 2012-10-25T11:37:54.270 回答
0

在除法之前,只需注意舍入规则。对于最简单的四舍五入:

if total % surplus < surplus / 2:
    return total / surplus
else:
    return (total / surplus) + 1

如果您需要进行适当的四舍五入,请稍微调整一下。

于 2010-10-16T20:38:06.443 回答
-2

这也应该有效:

def rint(n):
    return (int(n+.5) if n > 0 else int(n-.5))
于 2010-10-16T20:30:28.223 回答