计算大于或等于a / b的最小整数的最简单方法是什么?

时间:2009-08-20 15:24:38

标签: algorithm

rab是整数。

我需要最便宜的计算,因为在代码的关键部分。 我找到了:

r = (a / b) + (((a % b) != 0) ? 1 : 0);

如果b的幂为2,那么a / b可以替换为a >> log2(b)

a % b a & (b-1)可以节省大量的计算时间。

你知道更好的解决方案吗?

7 个答案:

答案 0 :(得分:29)

val r = (a + b - 1) / b

例如:

scala> for(a <- 1 to 10; b <- 1 to a) println("a: "+a+"\tb: "+b+"\tr: "+((a+b-1)/b))
a: 1    b: 1    r: 1
a: 2    b: 1    r: 2
a: 2    b: 2    r: 1
a: 3    b: 1    r: 3
a: 3    b: 2    r: 2
a: 3    b: 3    r: 1
a: 4    b: 1    r: 4
a: 4    b: 2    r: 2
a: 4    b: 3    r: 2
a: 4    b: 4    r: 1
a: 5    b: 1    r: 5
a: 5    b: 2    r: 3
a: 5    b: 3    r: 2
a: 5    b: 4    r: 2
a: 5    b: 5    r: 1
a: 6    b: 1    r: 6
a: 6    b: 2    r: 3
a: 6    b: 3    r: 2
a: 6    b: 4    r: 2
a: 6    b: 5    r: 2
a: 6    b: 6    r: 1
a: 7    b: 1    r: 7
a: 7    b: 2    r: 4
a: 7    b: 3    r: 3
a: 7    b: 4    r: 2
a: 7    b: 5    r: 2
a: 7    b: 6    r: 2
a: 7    b: 7    r: 1
a: 8    b: 1    r: 8
a: 8    b: 2    r: 4
a: 8    b: 3    r: 3
a: 8    b: 4    r: 2
a: 8    b: 5    r: 2
a: 8    b: 6    r: 2
a: 8    b: 7    r: 2
a: 8    b: 8    r: 1
a: 9    b: 1    r: 9
a: 9    b: 2    r: 5
a: 9    b: 3    r: 3
a: 9    b: 4    r: 3
a: 9    b: 5    r: 2
a: 9    b: 6    r: 2
a: 9    b: 7    r: 2
a: 9    b: 8    r: 2
a: 9    b: 9    r: 1
a: 10   b: 1    r: 10
a: 10   b: 2    r: 5
a: 10   b: 3    r: 4
a: 10   b: 4    r: 3
a: 10   b: 5    r: 2
a: 10   b: 6    r: 2
a: 10   b: 7    r: 2
a: 10   b: 8    r: 2
a: 10   b: 9    r: 2
a: 10   b: 10   r: 1

这假定ab为正数。如果其中任何一个是负数,则取决于除法是对称还是浮动(现代语言和平台是对称的),以及ab的信号。

如果a*b >= 0,则公式按给定的方式工作。如果除法是对称且a*b < 0,则a / b会给出正确的答案。

答案 1 :(得分:5)

在标题中你问“最简单” - 然而问题暗示了最“有效”。你需要哪一个?在实践中,最简单的并不总是等同于最有效的。

因此,如果你需要最简单的方法,你可能应该使用你的语言的天花板功能(通常称为 ceil ),如果你需要最有效的 - 这真的取决于你正在使用的处理器上有很多(无论它是否实现了硬件和其他因素的划分)

另外,我对log2的性能持怀疑态度 - 但我可能错了。但有一点很清楚:为优化而优化几乎总是不太好。

答案 2 :(得分:3)

怎么样:

(a - 1) / b + 1;

显然你必须要注意自己是否为0或更低。负数不一定按照你期望的方式划分,这取决于语言和实施。

答案 3 :(得分:1)

模数可以实现为%n = a - (n *(a / n);

因此,考虑到这一点,您可以重写为

const int div = a / b;
r = div + (((a - (n * div)) != 0) ? 1 : 0 );

由于你只做一个div而不是2,所以会稍快一些。

编辑:如果b是一个常数,那么你实际上可以完全消除除法,并用一个“幻数”(与常数除数相关)乘以它将再次快一点。然后,编译器将使用常数除数进行此优化。

答案 4 :(得分:0)

这可能适用于您正在寻找的内容,也可能不适合,但大多数(如果不是全部)语言都可以访问数学上限函数。例如,在C#中,写Math.Ceiling(5/2)会产生3。

答案 5 :(得分:0)

由于没有指定语言,我也将在ANS Forth中编写解决方案......

: div ( a b -- r)
  FM/MOD     \ a b -- q rest
  IF 1+ THEN \ q rest -- r
;

答案 6 :(得分:-4)

如果您在桌面上,请尝试浮点数并围绕它们。但是我怀疑你能找到比两个int devisions和一个add更便宜的东西。

唯一的另一个选项是某些CPU支持的DIVMOD运算符。它将通过一次通话为您提供分组和其余部分。