我试图找到在网站上构建寻呼机的总页数(所以我希望结果是一个整数。我得到一个记录列表,我想将其分成每页 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的答案,这太棒了)。 当简单的数学就足够了时,我们确实不想要函数调用的开销(
Math.Truncate()
、Math.Ceiling()
等)。
OP的问题概括(鸽子洞原理)为:
如果每个盒子里只能容纳
物体,我需要多少个盒子来存放x
物体?y
解决方案:
(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 boxes
——前两个盒子各装有两个物体,最后一个盒子装有一个。
(x + y - 1) ÷ y =
(5 + 2 - 1) ÷ 2 =
6 ÷ 2 =
3
所以对于原来的问题,
x = list.Count()
,
y = 10
,它给出了不使用额外函数调用的解决方案:
(list.Count() + 9) / 10
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
基准测试是用 Java 进行的,因为我很了解 Hotspot 如何优化并确保它是一个公平的结果。有了这样的结果,任何统计数据、噪音或任何东西都无法玷污它。
整数 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);
无需库或函数。
使用正确的代码进行编辑。
list.Count()/10 + (list.Count()%10 >0?1:0)
- 太糟糕了,div + mod编辑第一: 2n 认为这可能更快(取决于优化):div * mul(mul 比 div 和 mod 更快)
int c=list.Count()/10;
if (c*10<list.Count()) c++;
edit2全部删除。忘记了最自然的(加 9 确保整数向上舍入)
(list.Count()+9)/10