#1 楼
找到了一个优雅的解决方案:int pageCount = (records + recordsPerPage - 1) / recordsPerPage;
资料来源:罗兰·巴克豪斯(Roland Backhouse),Number Conversion,2001年
评论
-1,因为Brandon DuRette指出了溢出错误
– Finnw
2011年5月4日9:21
Obvious先生说:请记住确保recordsPerPage不为零
–亚当·根特(Adam Gent)
11年5月19日在11:41
干得好,我不敢相信C#没有整数上限。
– gosukiwi
2012年8月29日在18:32
是的,在尝试几种更为复杂的方法之后,我在2017年中期遇到了这个好答案。
– Mifo
17年7月29日在23:41
对于具有适当Euclidian除法运算符的语言(例如Python),甚至更简单的方法是pageCount =-((-records)// recordsPerPage)。
–超级猫
18年7月4日在16:45
#2 楼
在CPU级别上转换为浮点和返回似乎是浪费时间。Ian Nelson的解决方案:到:
int pageCount = (records + recordsPerPage - 1) / recordsPerPage;
AFAICS,它没有布兰登·杜莱特(Brandon DuRette)指出的溢出错误,因为它只使用一次,所以不需要存储特别是recordsPerPage,如果它是从昂贵的函数中获取的,该函数是从配置文件或其他内容中获取值的。
即如果config.fetch_value使用数据库查找或其他方法,则这可能是低效率的:涉及内存,并且键入过多:
int pageCount = (records - 1) / recordsPerPage + 1;
这是全部一行,并且仅提取一次数据:
int pageCount = (records + config.fetch_value('records per page') - 1) / config.fetch_value('records per page');
评论
+1,零记录仍然返回1 pageCount的问题实际上很方便,因为我仍然想要1页,显示占位符/伪造行“没有符合条件的记录”,有助于避免任何情况下的“ 0页数”问题您使用的分页控件。
–提莫西·沃尔特斯(Timothy Walters)
2011-3-17的2:38
请注意,对于零个记录,两个解决方案不会返回相同的pageCount。此简化版本将为零记录返回1 pageCount,而Roland Backhouse版本将返回0 pageCount。如果这是您想要的,就很好,但是当由C#/ Java stylee整数除法执行时,两个方程式并不相等。
–伊恩·尼尔森(Ian Nelson)
2011年9月6日7:48在
从Nelson解决方案更改为简化后,人们进行细微编辑以使人们扫描它并丢失胸部(就像我第一次这样做!),带括号的简化为... int pageCount =((records-1)/ recordsPerPage) + 1;
–戴夫·海伍德
2014年5月2日在8:41
您应该在简化版本中添加括号,以使其不依赖于特定的操作顺序。即(((records-1)/ recordsPerPage)+ 1。
–马丁
16年2月5日在17:57
@Ian,此答案不会始终返回1。如果您的recordsPerPage为“ 1”并且有0条记录,则可以返回0:-1 / 1 + 1 =0。虽然这不是一个超常见的情况,但保持请注意,如果您允许用户调整页面大小。因此,要么不允许用户的页面大小为1,要么对页面大小进行检查,或者同时检查两者(最好是避免出现意外行为)。
–迈克尔
18年1月9日在23:39
#3 楼
对于C#,解决方案是将值转换为双精度值(因为Math.Ceiling取双精度值):int nPages = (int)Math.Ceiling((double)nItems / (double)nItemsPerPage);
在Java中,您应该对Math.ceil进行相同操作()。
评论
当op明确要求C#时,为什么这个答案如此之低!
–felickz
2012年10月1日20:46
您还需要将输出强制转换为int,因为Math.Ceiling根据输入类型返回双精度或十进制。
– DanM7
2012-10-17 21:28
因为它效率极低
– Zar Shardan
13年4月4日在13:05
它可能效率低下,但非常容易理解。给定计算页数通常每个请求执行一次,任何性能损失都是无法衡量的。
– Jared Kells
2015年4月7日在6:21
它几乎比“(除数+(除数-1))/除数”更具可读性;还慢,需要数学库。
–卷
17年4月24日在6:47
#4 楼
这应该给您您想要的。您肯定希望每页用x个项目除以y个项目,问题是出现不均匀数字时,因此,如果有部分页面,我们也要添加一页。评论
x / y + !!(x%y)避免了类C语言的分支。几率很好,但是您的编译器还是会这样做。
– Rhys Ulerich
2010-1-26的15:57
+1不会像上面的答案那样溢出...尽管仅将整数转换为Math.ceiling的double,然后再次返回,这对性能敏感的代码却不是一个好主意。
–齿轮
2015年2月25日,下午1:54
@RhysUlerich在c#中不起作用(无法将int直接转换为bool)。我认为rjmunro的解决方案是避免分支的唯一方法。
–smead
16年4月9日在1:05
#5 楼
Ian提供的整数数学解决方案很好,但存在整数溢出错误。假设变量全部为int
,则可以重写该解决方案以使用long
数学运算并避免错误:模数解决方案没有bug。评论
我认为您不会在提出的方案中实际遇到此错误。 2 ^ 31条记录需要分页。
– rjmunro
09年2月5日,0:18
@rjmunro,此处为真实示例
– Finnw
2011年5月4日,9:20
@finnw:AFAICS,该页面上没有一个实际的示例,只是有关其他人在理论上发现该错误的报告。
– rjmunro
11年11月29日在11:44
是的,我一直在指出该错误。可以永久存在许多错误,而不会引起任何问题。在有人报告它之前,JDK的binarySearch实现中存在相同形式的错误已有九年之久(googleresearch.blogspot.com/2006/06/…)。我想问题是,无论您遇到这种错误的可能性有多大,为什么不先解决它?
–布兰登·杜莱特
2011年11月29日17:59
另外,应该注意的是,重要的不仅仅是页面的元素数量,还有页面大小。因此,如果您正在构建一个库,并且有人选择不通过传递2 ^ 31-1(Integer.MAX_VALUE)作为页面大小来进行分页,则会触发该错误。
–布兰登·杜莱特
11年11月29日在18:03
#6 楼
尼克·贝拉迪(Nick Berardi)回答的一种避免分支的变体:如果(-r >> (Integer.SIZE - 1))
为零或负,则求值为0;如果r
为正,则求值为-1。因此,如果>>
从r
中减去则具有加1的效果。#7 楼
对于记录== 0,rjmunro的解决方案给出1。正确的解决方案是0。也就是说,如果您知道记录> 0(并且我确定我们都假定recordsPerPage> 0),那么rjmunro的解决方案就会给出正确的结果,并且不会有任何溢出问题。int pageCount = 0;
if (records > 0)
{
pageCount = (((records - 1) / recordsPerPage) + 1);
}
// no else required
所有整数数学解决方案都将比任何浮点解决方案更有效。
评论
此方法不太可能成为性能瓶颈。如果是这样,您还应该考虑分支机构的成本。
– Finnw
2011年5月4日13:14
#8 楼
需要扩展方法: public static int DivideUp(this int dividend, int divisor)
{
return (dividend + (divisor - 1)) / divisor;
}
此处无需检查(溢出,
DivideByZero
等),请随意添加。顺便说一下,对于那些担心方法调用开销的人来说,编译器可能会内联这样的简单函数,所以我认为这不是要关注的地方。干杯。P.S.您可能会发现也意识到这一点很有用(它会得到余数):
int remainder;
int result = Math.DivRem(dividend, divisor, out remainder);
评论
这是不正确的。例如:DivideUp(4,-2)返回0(应为-2)。它仅适用于从答案或函数界面不清楚的非负整数。
– Thash
17年4月25日在21:31
推销,为什么不做一些有用的操作,例如添加一些额外的检查,然后在数字为负数的情况下,而不是投票否决我的答案,并错误地做出笼统的声明:“这是不正确的”,而实际上这只是边缘案件。我已经明确表示您应该首先进行其他检查:“此处没有检查(溢出,DivideByZero等),您可以根据需要随意添加。”
–尼古拉斯·彼得森(Nicholas Petersen)
17-4-25在23:18
该问题提到“我特别在考虑如何显示分页控件”,因此无论如何负数都将超出范围。同样,做一些有用的事情,如果需要的话,建议增加检查,这是团队合作精神。
–尼古拉斯·彼得森(Nicholas Petersen)
17-4-25在23:22
我不是无礼的意思,对不起,如果您这么认为的话。问题是“如何对整数除法的结果取整”。作者提到了分页,但是其他人可能有不同的需求。我认为,如果您的函数以某种方式反映出它不适用于负整数会更好,因为从接口中看不出来(例如,不同的名称或参数类型)。要使用负整数,例如,您可以取除数和除数的绝对值,然后将结果乘以其符号。
– Thash
17年4月26日在7:51
#9 楼
另一种选择是使用mod()函数(或'%')。如果存在非零的余数,则将除法的整数结果递增。#10 楼
我执行以下操作,处理所有溢出: br />此外,对于当前页码(未询问,但可能有用):var totalPages = totalResults.IsDivisble(recordsperpage) ? totalResults/(recordsperpage) : totalResults/(recordsperpage) + 1;
#11 楼
如何在C#中累积整数除法的结果我很想知道在C#中这样做的最好方法是什么,因为我需要循环执行近十万次。其他人使用Math发布的解决方案在答案中排名很高,但是在测试中我发现它们很慢。 Jarod Elliott提出了一种更好的策略来检查mod是否产生任何东西。这是使用Math的代码:
#12 楼
在零测试中删除分支的替代方法:int pageCount = (records + recordsPerPage - 1) / recordsPerPage * (records != 0);
不确定是否可以在C#中工作,应该在C / C ++中工作。
#13 楼
可以迭代其结果的通用方法可能很有趣: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;
}
评论
番石榴也有类似的方法(Lists.partition(List,int)),具有讽刺意味的是,生成的List的size()方法(截至r09)遭受了Brandon DuRette的回答中提到的溢出错误。
– Finnw
2011年5月4日13:21
#14 楼
我有类似的需要,我需要将分钟转换为小时和分钟。我使用的是: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);
#15 楼
下面的方法应比上述解决方案更好地舍入,但是要以性能为代价(由于浮点计算为0.5 * rctDenominator):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;
}
评论
我想念什么吗? y / x +1效果很好(前提是您知道/运算符总是四舍五入)。@rikkit-如果y和x相等,则y / x +1太高。
对于刚刚发现此问题的任何人,此重复问题的答案除了提供了明确的解释外,还避免了不必要的转换为双精度,并避免了溢出问题。
@IanNelson更一般地说,如果x可被y整除,则y / x +1会太高。
@ ZX9不,它不能避免溢出问题。它与Ian Nelson在此处发布的解决方案完全相同。