如何始终向上舍入到下一个整数[重复]

问题描述 投票:0回答:8

我试图找到在网站上构建寻呼机的总页数(所以我希望结果是一个整数。我得到一个记录列表,我想将其分成每页 10 个(页数)

当我这样做时:

list.Count() / 10

list.Count() / (decimal)10

list.Count() =12
,我得到了
1
的结果。

我该如何编码,以便在这种情况下得到

2
(其余部分应始终添加
1

c# rounding
8个回答
193
投票
Math.Ceiling((double)list.Count() / 10);

91
投票

(list.Count() + 9) / 10

这里的其他所有内容要么矫枉过正,要么根本就是错误的(除了bestsss的答案,这太棒了)。 当简单的数学就足够了时,我们确实想要函数调用的开销(

Math.Truncate()
Math.Ceiling()
等)。


OP的问题概括(鸽子洞原理)为:

如果每个盒子里只能容纳

x
物体,我需要多少个盒子来存放
y
物体?

解决方案:

  1. 源于最后一个盒子可能部分为空的认识,并且
  2. (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


    


25
投票
适当的基准或数字可能如何

在关于

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); } }
    

17
投票
这也可以:

c = (count - 1) / 10 + 1;
    

5
投票
我认为最简单的方法是将两个整数相除并加一:

int r = list.Count() / 10; r += (list.Count() % 10 == 0 ? 0 : 1);

无需库或函数。

使用正确的代码进行编辑。


3
投票
您可以使用Math.Ceiling

http://msdn.microsoft.com/en-us/library/system.math.ceiling%28v=VS.100%29.aspx


1
投票
使用 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; if (c*10<list.Count()) c++;

edit2全部删除。忘记了最自然的(加 9 确保整数向上舍入)

(list.Count()+9)/10


    

© www.soinside.com 2019 - 2024. All rights reserved.