整数除法结果如何取整?

我特别考虑的是如何在使用c#或Java等语言时显示分页控件。

如果我有x项,我想在每页的y块中显示,将需要多少页?

255459 次浏览

您需要执行浮点除法,然后使用ceiling函数将值四舍五入到下一个整数。

另一种替代方法是使用mod()函数(或'%')。如果有非零余数,则对除法的整数结果加1。

这应该能给你想要的。你肯定想要每页x个项目除以y个项目,问题是当出现不平衡的数字时,所以如果有一个部分页面,我们也想增加一页。

int x = number_of_items;
int y = items_per_page;


// with out library
int pages = x/y + (x % y > 0 ? 1 : 0)


// with library
int pages = (int)Math.Ceiling((double)x / (double)y);

对于c#,解决方案是将值强制转换为double类型(如Math。天花板是双人间):

int nPages = (int)Math.Ceiling((double)nItems / (double)nItemsPerPage);

在java中,您应该对Math.ceil()执行相同的操作。

找到了一个优雅的解决方案:

int pageCount = (records + recordsPerPage - 1) / recordsPerPage;

来源:数字转换,罗兰·巴恪思,2001年

Ian提供的整数数学解决方案很好,但存在整数溢出错误。假设变量都是int,解决方案可以重写为使用long数学并避免错误:

int pageCount = (-1L + records + recordsPerPage) / recordsPerPage;

如果recordslong,则错误仍然存在。模解没有这个bug。

在CPU级别上,转换为浮点数和返回浮点数似乎是一种巨大的时间浪费。

伊恩·尼尔森的解决方案:

int pageCount = (records + recordsPerPage - 1) / recordsPerPage;

可以简化为:

int pageCount = (records - 1) / recordsPerPage + 1;

AFAICS,它没有Brandon DuRette指出的溢出错误,并且因为它只使用一次,所以您不需要存储recordsPerPage,特别是如果它来自一个从配置文件或其他东西获取值的昂贵函数。

例如,这可能是低效的,如果配置。Fetch_value使用了数据库查找之类的:

int pageCount = (records + config.fetch_value('records per page') - 1) / config.fetch_value('records per page');

这会创建一个你并不真正需要的变量,这可能有(轻微的)内存影响,并且输入太多:

int recordsPerPage = config.fetch_value('records per page')
int pageCount = (records + recordsPerPage - 1) / recordsPerPage;

这都是一行,只获取一次数据:

int pageCount = (records - 1) / config.fetch_value('records per page') + 1;

对于records == 0, rjmunro解为1。正确的解是0。也就是说,如果您知道记录> 0(我确信我们都假设recordsPerPage > 0),那么rjmunro解决方案将给出正确的结果,并且没有任何溢出问题。

int pageCount = 0;
if (records > 0)
{
pageCount = (((records - 1) / recordsPerPage) + 1);
}
// no else required

所有的整数数学解将比浮点解的任何更有效。

在测试中删除零分支的替代方法:

int pageCount = (records + recordsPerPage - 1) / recordsPerPage * (records != 0);

不确定这是否将工作在c#,应该在C/ c++。

一个泛型方法,你可以迭代它的结果:

public static Object[][] chunk(Object[] src, int chunkSize) {


int overflow = src.length%chunkSize;
int numChunks = (src.length/chunkSize) + (overflow>0?1:0);
Object[][] dest = new Object[numChunks][];
for (int i=0; i<numChunks; i++) {
dest[i] = new Object[ (i<numChunks-1 || overflow==0) ? chunkSize : overflow ];
System.arraycopy(src, i*chunkSize, dest[i], 0, dest[i].length);
}
return dest;
}

避免分支的尼克·贝拉尔迪的回答的变体:

int q = records / recordsPerPage, r = records % recordsPerPage;
int pageCount = q - (-r >> (Integer.SIZE - 1));

注意:(-r >> (Integer.SIZE - 1))r的符号位组成,重复32次(多亏了>>操作符的符号扩展)。如果r为0或负,则返回0;如果r为正,则返回-1。因此,从q中减去它的效果是,如果records % recordsPerPage > 0则加1。

我有一个类似的需要,我需要将分钟转换为小时;分钟。我用的是:

int hrs = 0; int mins = 0;


float tm = totalmins;


if ( tm > 60 ) ( hrs = (int) (tm / 60);


mins = (int) (tm - (hrs * 60));


System.out.println("Total time in Hours & Minutes = " + hrs + ":" + mins);

下面的方法应该比上面的解决方案做得更好,但以性能为代价(由于0.5* rct分母的浮点计算):

uint64_t integerDivide( const uint64_t& rctNumerator, const uint64_t& rctDenominator )
{
// Ensure .5 upwards is rounded up (otherwise integer division just truncates - ie gives no remainder)
return (rctDenominator == 0) ? 0 : (rctNumerator + (int)(0.5*rctDenominator)) / rctDenominator;
}

我做以下,处理任何溢出:

var totalPages = totalResults.IsDivisble(recordsperpage) ? totalResults/(recordsperpage) : totalResults/(recordsperpage) + 1;

并使用这个扩展,如果有0结果:

public static bool IsDivisble(this int x, int n)
{
return (x%n) == 0;
}

此外,对于当前的页码(没有被问到,但可能有用):

var currentPage = (int) Math.Ceiling(recordsperpage/(double) recordsperpage) + 1;

需要扩展方法:

    public static int DivideUp(this int dividend, int divisor)
{
return (dividend + (divisor - 1)) / divisor;
}

这里没有支票(overflow, DivideByZero等),如果你喜欢,可以随意添加。顺便说一下,对于那些担心方法调用开销的人来说,像这样的简单函数无论如何都可能被编译器内联,所以我不认为这是需要担心的地方。欢呼。

附注:你可能会发现意识到这一点也很有用(它得到余数):

    int remainder;
int result = Math.DivRem(dividend, divisor, out remainder);

如何在c#中四舍五入整数除法的结果

我有兴趣知道在c#中做这件事的最好方法是什么,因为我需要在循环中做这件事近10万次。其他人使用数学发布的解决方案在答案中排名很高,但在测试中我发现它们很慢。Jarod Elliott提出了一个更好的策略来检查mod是否产生任何东西。

int result = (int1 / int2);
if (int1 % int2 != 0) { result++; }

我循环运行了100万次,花了8毫秒。下面是使用数学的代码:

int result = (int)Math.Ceiling((double)int1 / (double)int2);

在我的测试中运行了14毫秒,相当长的时间。

你可以使用

(int)Math.Ceiling(((decimal)model.RecordCount )/ ((decimal)4));

我为自己做了这个,感谢贾罗德艾略特 &SendETHToThisAddress答道。

public static int RoundedUpDivisionBy(this int @this, int divider)
{
var result = @this / divider;
if (@this % divider is 0) return result;
return result + Math.Sign(@this * divider);
}
然后我意识到与顶部的答案相比,它对CPU来说是过度的。 但是,我认为它是可读的,也适用于负数