Math.Ceiling
returns double
because double
may store much bigger numbers.
However if i'm sure that int
type is capable to store the result how should I convert? Is it safe to cast (int) Math.Ceiling(...
?

- 23,239
- 54
- 171
- 305
-
http://stackoverflow.com/questions/5693468/why-math-ceiling-returns-double – Nahum Jan 12 '12 at 09:53
-
A note about int and maxsize: I have a constant anxiety for all my int(identity/auto_number) when designing databases, but seriously 2,147,483,647 is a pretty big number... To quote Bill Gates: "640K ought to be enough for anybody". – Fredrik Johansson Jan 12 '12 at 09:59
-
@NahumLitvin referenced question is `why` question, my question is `how` question – Oleg Vazhnev Jan 12 '12 at 10:02
-
ps the Bill Gates quote about 640k is a myth... so many seem to want it to be true – PandaWood Sep 08 '14 at 02:20
6 Answers
If you are sure that you do not cross the capacity of int, it should be perfectly safe to do
int myInt = (int)Math.Ceiling(...);
If you are not sure about the bound, you could go with long
instead of int
.

- 59,338
- 27
- 124
- 151
-
Except that nothing prevents a double from exceeding the bounds for doubles, too – Falanwe Jan 12 '12 at 10:08
-
I guess you mean long exceeding the bounds.... ;) But of course it does not, but it gives a lot more playing room. If he exceed even long, he would simply need to keep it as a double. – Øyvind Bråthen Jan 12 '12 at 10:10
-
Of course, I meant double exceeding the bounds for long. Stupid typo ^^ – Falanwe Jan 12 '12 at 13:29
From C++ practices, I would use the following. It's guaranteed to get the correct result even when ceiling returns 99.99999...8 or 100.000000...1
var result = (int)(Math.Ceiling(value) + 0.5);
The code below should work too if you trust its implementation
var result = Convert.ToInt32(value);

- 7,974
- 3
- 32
- 43

- 748
- 6
- 17
-
2Do I really need `+0.5`? That's what my question about. So far it seems I do not need that ugly code. – Oleg Vazhnev Jan 12 '12 at 10:05
-
You need + 0.5 to avoid double rounding error. For exemple (int)103.919 is 104 instead of 103. Convert.ToInt32 does not have this problem, as it rounds toward the nearest integer. – Falanwe Jan 12 '12 at 13:30
-
9Math.Ceiling() returns an integer value (of a double or decimal type). It won't return fractions, so no need to "re-round" it with the 0.5 – goodeye Feb 02 '17 at 23:33
If it's all about speed, then Math.Ceiling for Int inputs and output is quite slow. The fastest is an inline expression. 2.4 seconds vs 33 ms.
Warning: Only for positive value
and divisor
values.
A) Modulus
Here's one I came up with, that has obviously also been found by C/C++ developers before:
var ceilingResult = (value / divisor) + (value % divisor == 0 ? 0 : 1);
From my own benchmark of 10M iterations, Math.Ceiling takes ~2.4 seconds. Calling this expression inside a named function takes ~380 ms and having it as a direct inline expression takes ~33ms.
B) Simple arithmetic only
Also consider using the suggestion from @mafu
var ceilingResult = (value + divisor - 1) / divisor;
See this 470x upvoted C++ answer for reference and validation. Also https://stackoverflow.com/a/4175152/887092.
C) DivRem
While looking at this answer, https://stackoverflow.com/a/14878734/887092, I noticed the comment that reminded me about DivRem CPU instructions. See https://learn.microsoft.com/en-us/dotnet/api/system.math.divrem?view=netframework-4.8. Math.DivRem
should get resolved down to such a CPU instruction.
var quotient = Math.DivRem(value, divisor, out long remainder);
var ceilingResult = quotient + (remainder == 0 ? 0 : 1);
[I have not tested this]. See https://stackoverflow.com/a/924160/887092, for potential edge cases (Where negative Int numbers are used)
Further optimisations might be possible for this - maybe with casting. In this answer, https://stackoverflow.com/a/924160/887092, an if-conditional statement is used - they are about the same.
Performance of the 3:
- Modulus: Has two operations that are added, but also a conditional branch.
- Arithmetic: Has some additional mathematical operations in a sequence.
- DivRem: Builds on the Modulus approach. If C# does resolve Math.DivRem to a single CPU instruction, this might be faster. Further optimisations might also be possible.
I'm not sure how the two would perform on various architectures. But now you have options to explore.
If you would like Math.Floor for Int inputs and Output, it's even easier:
var floorResult = (value / divisor);

- 17,547
- 6
- 53
- 70
-
I must stress that this only works when you are doing division with `value` and `divisor`, and when both `value` and `divisor` are integers. My scenario is, "how many AESEncryption blocks are required when encrypting a given amount of plain text bytes" where plain text bytes count is `value`, and `divisor` is the amount of bytes in an AESEncryption block. For example, 9 bytes with a block size of 16 will require 2 blocks. – Kind Contributor May 29 '19 at 10:50
-
-
@mafu it seems to me that should work. If it does - that's a great improvement. – Kind Contributor Mar 20 '22 at 23:07
If you are uncertain you can always put an if statement and check if the number you get back is highter then int.MaxValue

- 1,697
- 16
- 24
int oInt = Convert.ToInt32(Math.Ceiling(value));
since Math.Ceiling
returns double
and you want to convert it to int
, use Convert
Class.
example:
double[] values= { Double.MinValue, -1.38e10, -1023.299, -12.98,
0, 9.113e-16, 103.919, 17834.191, Double.MaxValue };
int result;
foreach (double value in values)
{
try {
result = Convert.ToInt32(value);
Console.WriteLine("Converted the {0} value '{1}' to the {2} value {3}.",
value.GetType().Name, value,
result.GetType().Name, result);
}
catch (OverflowException) {
Console.WriteLine("{0} is outside the range of the Int32 type.", value);
}
}
// -1.79769313486232E+308 is outside the range of the Int32 type.
// -13800000000 is outside the range of the Int16 type.
// Converted the Double value '-1023.299' to the Int32 value -1023.
// Converted the Double value '-12.98' to the Int32 value -13.
// Converted the Double value '0' to the Int32 value 0.
// Converted the Double value '9.113E-16' to the Int32 value 0.
// Converted the Double value '103.919' to the Int32 value 104.
// Converted the Double value '17834.191' to the Int32 value 17834.
// 1.79769313486232E+308 is outside the range of the Int32 type.

- 258,903
- 69
- 498
- 492
-
1I can't see `Math.Ceiling` anywhere in here. Did you read the question? – Øyvind Bråthen Jan 12 '12 at 09:57
-
I don't need to `catch` OverflowException because i'm sure I do not have `OverflowException`. So I would prefer to propogate this kind of exception and so cast should work in my case. – Oleg Vazhnev Jan 12 '12 at 10:04
-