给定整数值x
和y
,C和C ++都返回等价的浮点数q = x/y
的商ceil(10/5)=2
。我对一种返回天花板的方法很感兴趣。例如,ceil(11/5)=3
和q = x / y;
if (q * y < x) ++q;
。
显而易见的方法包括:
float
这需要额外的比较和乘法;我见过的其他方法(事实上使用)涉及作为double
或{{1}}进行投射。是否有更直接的方法可以避免额外的乘法(或第二个除法)和分支,并且还可以避免将其作为浮点数进行转换?
答案 0 :(得分:340)
正数
unsigned int x, y, q;
要整理......
q = (x + y - 1) / y;
或(避免x + y溢出)
q = 1 + ((x - 1) / y); // if x != 0
答案 1 :(得分:60)
对于正数:
q = x/y + (x % y != 0);
答案 2 :(得分:57)
Sparky的答案是解决这个问题的一种标准方法,但正如我在评论中写的那样,你冒着溢出的风险。这可以通过使用更宽的类型来解决,但是如果要分割long long
s?
我的解决方案是:
q = (x % y) ? x / y + 1 : x / y;
它会比OPs代码略快,因为模数和除法是在处理器上使用相同的指令执行的,因为编译器可以看到它们是等价的。至少gcc 4.4.1在x86上使用-O2标志执行此优化。
理论上,编译器可能会在Nathan Ernst的代码中内联函数调用并发出相同的内容,但是当我测试它时gcc没有这样做。这可能是因为它会将编译后的代码绑定到标准库的单个版本。
作为最后一点,在现代机器上,这一切都不重要,除非你处于一个非常紧凑的循环中并且所有数据都在寄存器或L1缓存中。否则所有这些解决方案都会同样快,除了可能是Nathan Ernst之外,如果必须从主存储器中取出函数,这可能会明显变慢。
答案 3 :(得分:16)
您可以使用cstdlib中的div
函数来获取商和&amp;在单个调用中剩余,然后单独处理上限,如下面的
#include <cstdlib>
#include <iostream>
int div_ceil(int numerator, int denominator)
{
std::div_t res = std::div(numerator, denominator);
return res.rem ? (res.quot + 1) : res.quot;
}
int main(int, const char**)
{
std::cout << "10 / 5 = " << div_ceil(10, 5) << std::endl;
std::cout << "11 / 5 = " << div_ceil(11, 5) << std::endl;
return 0;
}
答案 4 :(得分:12)
这个怎么样? (要求y为非负数,所以在极少数情况下不要使用它,其中y是一个没有非负性保证的变量)
q = (x > 0)? 1 + (x - 1)/y: (x / y);
我将y/y
缩减为1,取消了x + y - 1
一词,并且有任何溢出的可能性。
当x - 1
为无符号类型且包含零时,我避免x
缠绕。
对于签名x
,否定和零仍然合并为一个案例。
对于现代通用CPU而言,可能不是一个巨大的好处,但在嵌入式系统中,这比任何其他正确的答案要快得多。
答案 5 :(得分:5)
正面和负面x
都有一个解决方案,但仅适用于只有1个分区且没有分支的正y
:
int ceil(int x, int y) {
return x / y + (x % y > 0);
}
注意,如果x
为正,那么除法为零,如果提醒不为零,我们应该加1。
如果x
为负数,则除法为零,这是我们需要的,我们不会添加任何内容,因为x % y
不是正数
答案 6 :(得分:4)
这适用于正数或负数。
q = x/y+((x%y!=0)?!((x>0)^(y>0)):0);
如果有余数,检查x和y是否具有相同的符号并相应地加1。
答案 7 :(得分:2)
答案 8 :(得分:1)
我本来想发表评论,但是我的代表不够高。
据我所知,对于+ ve&pow为2的情况,这是最快的方法(在CUDA中进行了测试)
//example y=8
q = x >> 3 + !!(x & 7);
否则(也仅+ ve),我倾向于这样做:
q = x/y + !!(x % y);
答案 9 :(得分:1)
对于有符号或无符号整数。
q = x / y + !(((x < 0) != (y < 0)) || !(x % y));
对于有符号的被除数和无符号的除数。
q = x / y + !((x < 0) || !(x % y));
对于无符号股息和有符号除数。
q = x / y + !((y < 0) || !(x % y));
对于无符号整数。
q = x / y + !!(x % y);
零除数失败(与本机操作一样)。不能导致溢出。
此处对应的下限和模 constexpr
实现,以及用于选择必要重载的模板(作为完全优化并防止不匹配的符号比较警告):
https://github.com/libbitcoin/libbitcoin-system/wiki/Integer-Division-Unraveled
答案 10 :(得分:-2)
使用O3进行编译,编译器可以很好地进行优化。
q = x / y;
if (x % y) ++q;