C# 如何始终向上取整到下一个整数
我试图在网站上构建寻呼机时查找总页面数(因此我希望结果是一个整数。我得到一个记录列表,并希望将每页分成10页(页面计数) 当我这样做时:C# 如何始终向上取整到下一个整数,c#,language-agnostic,rounding,C#,Language Agnostic,Rounding,我试图在网站上构建寻呼机时查找总页面数(因此我希望结果是一个整数。我得到一个记录列表,并希望将每页分成10页(页面计数) 当我这样做时: list.Count() / 10 或 而list.Count()=12,我得到的结果是1 在这种情况下,我应该如何编码才能得到2(剩余部分应始终添加1)您可以使用Math 使用mod检查-如果有余数,只需将该值增加1即可。对于简单的ceil,是否转换为双倍(并返回) list.Count()/10+(list.Count()%10>0?1:0)-这很糟糕,
list.Count() / 10
或
而list.Count()=12
,我得到的结果是1
在这种情况下,我应该如何编码才能得到
2
(剩余部分应始终添加1
)您可以使用Math
使用mod检查-如果有余数,只需将该值增加1即可。对于简单的ceil,是否转换为双倍(并返回)
list.Count()/10+(list.Count()%10>0?1:0)
-这很糟糕,div+mod
第一次编辑:
根据2n的想法,这可能更快(取决于优化):div*mul(mul比div和mod快)
int c=list.Count()/10;
如果(c*10我认为最简单的方法是将两个整数除以一:
int r = list.Count() / 10;
r += (list.Count() % 10 == 0 ? 0 : 1);
不需要库或函数
使用正确的代码编辑。(list.Count()+9)/10
这里的其他一切要么是矫枉过正,要么就是完全错误(除了,这太棒了)。当简单的数学足够时,我们确实不想要函数调用的开销(Math.Truncate()
,Math.天花()
,等等)
OP的问题将()概括为:
如果每个框中只包含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个框
——前两个框分别容纳两个对象,最后一个框容纳一个对象
(x + y - 1) ÷ y =
(5 + 2 - 1) ÷ 2 =
6 ÷ 2 =
3
因此,对于原始问题,x=list.Count()
,y=10
,它给出了不使用额外函数调用的解决方案:
(list.Count()+9)/10
这同样适用于:
c = (count - 1) / 10 + 1;
一个合适的基准或数字可能如何
在关于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是如何优化的,并确保它是一个公平的结果
Integer 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);
}
}
t1包;
导入java.math.BigDecimal;
导入java.util.Random;
公共课组{
静态int[]vals;
静态长双细胞(){
int[]v=VAL;
长和=0;
对于(int i=0;i(list.Count()+9)/10-这是最好的:)Math.Round(8.28,0,middpointrounding.AwayFromZero)将int转换为浮点对于这样一个简单的operation@Rob,您可以执行..两次,int->floating point(double)->int。它需要CPU的双重刷新,解决方案可能是最差的正确方案(对于int,但不长)一百万个周期的执行时间之差为0.01ms。我认为处理时间的微小增加带来的额外可读性是值得的。@Rob-差异不仅仅在于浮点转换,还包括对上限()调用的额外函数调用开销。这不是“额外可读性”,而是“额外工作"这不是正确的方法。这个问题会被无数次地问到,因此有一个更好的解决方案,它不涉及类型转换和额外的函数调用。新程序员需要学习正确的方法。事实证明,正确地做这件事是很容易理解的,看到有人做错事会调用所有的函数他们的代码成了问题。这些家伙在抱怨分页公式的基准测试…Rob的答案是最佳人选。它干净简单,而且你不会在某个迭代中处理数百次…一旦你有了一个列表,你只需要知道页数,这种从int到double再到int的类型转换麻烦只需要纳秒总有一天可能会有一瞬间。甚至不值得花时间诚实地写下此评论作为回应。有时甚至在此处或此处添加毫秒也值得简化。当计数%10==0时,这不会正常工作。即,如果list.count()返回2表示10不正确==除法前的10。当1正确时,你得到2。哎呀,错过了。你们是对的,伙计:)你必须先做mod,然后进行测试,然后进行增量(这是一个加法和一个存储)。太贵了。只做加法然后除法更容易(和mod一样贵)。无需测试。回答很好。断言是一回事,证明完全是另一回事。好的一点,证明是另一回事。我认为你的代码有很多问题,特别是像0和20这样的数字(将返回3)或者任何大于10的数字。@Rumplin,您对0的估计是正确的,但对于20,它会返回预期的2。您是对的,对于数字>0,它可以正常工作。这是一个很好的解决方案,但在我看来,这比使用Math.天花板可读性差。乍一看,不清楚代码是什么
c = (count - 1) / 10 + 1;
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
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);
}
}