r
,a
和b
是整数。
我需要最便宜的计算,因为在代码的关键部分。 我找到了:
r = (a / b) + (((a % b) != 0) ? 1 : 0);
如果b的幂为2,那么a / b
可以替换为a >> log2(b)
和a % b
a & (b-1)
可以节省大量的计算时间。
你知道更好的解决方案吗?
答案 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
这假定a
和b
为正数。如果其中任何一个是负数,则取决于除法是对称还是浮动(现代语言和平台是对称的),以及a
和b
的信号。
如果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
运算符。它将通过一次通话为您提供分组和其余部分。