我正在尝试在网站上构建分页功能,需要找出总页数(结果应该是一个整数)。我有一组记录,我想每页显示10条记录(作为分页计数)。
当我执行以下操作时:
list.Count() / 10
或者list.Count() / (decimal)10
当 list.Count() = 12
时,我得到的结果是 1
。
我该如何编写代码才能在这种情况下获得 2
(余数应始终加上 1
)?
我正在尝试在网站上构建分页功能,需要找出总页数(结果应该是一个整数)。我有一组记录,我想每页显示10条记录(作为分页计数)。
当我执行以下操作时:
list.Count() / 10
或者list.Count() / (decimal)10
当 list.Count() = 12
时,我得到的结果是 1
。
我该如何编写代码才能在这种情况下获得 2
(余数应始终加上 1
)?
Math.Ceiling((double)list.Count() / 10);
(list.Count() + 9) / 10
这里的其他内容都有点过度或者完全错误(除了bestsss' answer,那个太棒了)。当简单的数学运算就足够时,我们不需要函数调用(如Math.Truncate()
、Math.Ceiling()
等)。
原帖提出的问题是概括性的(pigeonhole principle):
如果一个箱子只能装下
y
个物品,那么要存储x
个物品需要多少个箱子?
解决方法:
(x + y - 1) ÷ y
。你可以回忆一下小学三年级学过的数学知识,整数除法就是指5 ÷ 2 = 2
。
浮点除法是指5 ÷ 2 = 2.5
,但在这里我们不需要它。
许多编程语言支持整数除法。在C语言的衍生语言中,当你对int
类型(如short
、int
、long
等)进行除法时,你会自动得到整数除法的结果,即余数/小数部分被舍去,因此:
5 / 2 == 2
将原来的问题替换为x = 5
和y = 2
,就变成了:
如果一个箱子只能装下2个物品,那么要存储5个物品需要多少个箱子?
答案现在显而易见:3个箱子
——前两个箱子每个装2个物品,最后一个箱子装1个。
(x + y - 1) ÷ y =
(5 + 2 - 1) ÷ 2 =
6 ÷ 2 =
3
针对原问题,假设x = list.Count()
,y = 10
,以下代码可不使用其他函数调用解决:
(list.Count() + 9) / 10
count()
无法适应64位整数(甚至是32位整数),那么你可能有更大的问题。 - undefined在关于 Math.ceil(value/10d)
和 (value+9)/10
的讨论中,我最终编写了一个适当的非死代码、非解释模式基准测试。
我一直在说编写微基准测试并不容易。下面的代码说明了这一点:
00:21:40.109 starting up....
00:21:40.140 doubleCeil: 19444599
00:21:40.140 integerCeil: 19444599
00:21:40.140 warming up...
00:21:44.375 warmup doubleCeil: 194445990000
00:21:44.625 warmup integerCeil: 194445990000
00:22:27.437 exec doubleCeil: 1944459900000, elapsed: 42.806s
00:22:29.796 exec integerCeil: 1944459900000, elapsed: 2.363s
由于我很清楚Hotspot如何进行优化并确保结果是公平的,所以基准测试使用Java。通过这样的结果,没有统计数据、噪音或任何东西可以玷污它。
整数ceil函数非常快。
代码:
package t1;
import java.math.BigDecimal;
import java.util.Random;
public class Div {
static int[] vals;
static long doubleCeil(){
int[] v= vals;
long sum = 0;
for (int i=0;i<v.length;i++){
int value = v[i];
sum+=Math.ceil(value/10d);
}
return sum;
}
static long integerCeil(){
int[] v= vals;
long sum = 0;
for (int i=0;i<v.length;i++){
int value = v[i];
sum+=(value+9)/10;
}
return sum;
}
public static void main(String[] args) {
vals = new int[7000];
Random r= new Random(77);
for (int i = 0; i < vals.length; i++) {
vals[i] = r.nextInt(55555);
}
log("starting up....");
log("doubleCeil: %d", doubleCeil());
log("integerCeil: %d", integerCeil());
log("warming up...");
final int warmupCount = (int) 1e4;
log("warmup doubleCeil: %d", execDoubleCeil(warmupCount));
log("warmup integerCeil: %d", execIntegerCeil(warmupCount));
final int execCount = (int) 1e5;
{
long time = System.nanoTime();
long s = execDoubleCeil(execCount);
long elapsed = System.nanoTime() - time;
log("exec doubleCeil: %d, elapsed: %.3fs", s, BigDecimal.valueOf(elapsed, 9));
}
{
long time = System.nanoTime();
long s = execIntegerCeil(execCount);
long elapsed = System.nanoTime() - time;
log("exec integerCeil: %d, elapsed: %.3fs", s, BigDecimal.valueOf(elapsed, 9));
}
}
static long execDoubleCeil(int count){
long sum = 0;
for(int i=0;i<count;i++){
sum+=doubleCeil();
}
return sum;
}
static long execIntegerCeil(int count){
long sum = 0;
for(int i=0;i<count;i++){
sum+=integerCeil();
}
return sum;
}
static void log(String msg, Object... params){
String s = params.length>0?String.format(msg, params):msg;
System.out.printf("%tH:%<tM:%<tS.%<tL %s%n", new Long(System.currentTimeMillis()), s);
}
}
这种方法也可以使用:
c = (count - 1) / 10 + 1;
我认为最简单的方法是将两个整数分别除以一后再加上一:
int r = list.Count() / 10;
r += (list.Count() % 10 == 0 ? 0 : 1);
为了实现一个简单的ceil,如何将Xform转换为double(然后再转回来)?
list.Count() / 10 + (list.Count() % 10 > 0 ? 1 : 0)
- 这样做不好,除法和取模都用到了
编辑第一条: 经过第二次考虑,以下方法可能更快(取决于优化):除法 * 乘法(乘法比除法和取模都更快)
int c=list.Count()/10;
if (c*10<list.Count()) c++;
编辑2 所有的鞋子。忘记了最自然的方法(添加9确保整数四舍五入)
(list.Count()+9)/10
通过使用模运算进行检查 - 如果有余数,只需将值增加一。