C# Double to Int Conversion: Casting and Rounding
c# double to int conversion: Learn how to convert double to int in C# using casting, Convert.ToInt32, and Math methods, including rounding behavior and overflow handling.
When you need to convert a double to an int in C#, the choice of method determines how the fractional part is handled, whether overflow throws, and how readable the intent is. This article covers the common approaches for c# double to int conversion: the direct cast, Convert.ToInt32, and the Math rounding methods, along with the edge cases that affect production code.
The Direct Cast: Truncation by Default
The simplest way to convert a double to an int is to use a cast: (int)doubleValue. This operation truncates the value toward zero, meaning it discards the fractional part without rounding. For example:
double d = 3.7; int i = (int)d; // i == 3
The cast works for negative numbers as well: (int)-3.7 yields -3, not -4. This behavior is consistent with the C# specification for floating-point to integral conversions. The cast is performed in an unchecked context by default, so if the value is outside the range of int (i.e., less than int.MinValue or greater than int.MaxValue), the result is undefined and may wrap around without throwing an exception. We'll look at checked contexts later.
Convert.ToInt32: Banker's Rounding
The Convert.ToInt32(double) method takes a different approach: it rounds the value to the nearest integer, using banker's rounding (also known as round-half-to-even). This means that midpoint values like 2.5 and 3.5 round to the nearest even integer: 2 and 4, respectively.
double a = 2.5; double b = 3.5; int x = Convert.ToInt32(a); // x == 2 int y = Convert.ToInt32(b); // y == 4
This behavior differs from the common "round half up" taught in schools, so it can surprise developers who expect 3.5 to become 4. If you need midpoint rounding away from zero, use Math.Round with an explicit MidpointRounding option, as shown in the next section.
Convert.ToInt32 also throws an OverflowException if the input is outside the int range, which is a safer behavior than the unchecked cast.
Math.Round, Math.Floor, Math.Ceiling: Explicit Control
When you need precise control over rounding direction, the Math class provides dedicated methods. Math.Round rounds to the nearest integer, with a MidpointRounding parameter to select the midpoint strategy:
double d = 3.5; int roundAway = (int)Math.Round(d, MidpointRounding.AwayFromZero); // 4 int roundEven = (int)Math.Round(d, MidpointRounding.ToEven); // 4 (but for 2.5 it would be 2)
Math.Floor always rounds down (toward negative infinity), and Math.Ceiling always rounds up (toward positive infinity):
double d = 3.7; int floor = (int)Math.Floor(d); // 3 int ceil = (int)Math.Ceiling(d); // 4
These methods return double or decimal, so you still need a cast to int if you require an integral type. The cast after Math.Floor is safe because the result is already an integer value, but the cast itself truncates—which is harmless here since the value has no fractional part.
Handling Overflow and Checked Contexts
The direct cast in C# is unchecked by default. If the double value is too large or too small for an int, the cast produces an unspecified result, often wrapping around to an arbitrary value. To force an overflow check, wrap the conversion in a checked block:
double huge = 1e10; try { int i = checked((int)huge); // throws OverflowException } catch (OverflowException) { // handle overflow }
Convert.ToInt32 always performs a range check and throws OverflowException if the value is out of range. This makes it a better choice when you cannot guarantee that the input is within the int bounds. Note that Math.Round, Math.Floor, and Math.Ceiling do not perform overflow checks on the result; they return a double that you then cast, so the cast is subject to the same unchecked behavior unless you use checked.
Precision and Edge Cases: NaN, Infinity, and Large Values
Floating-point numbers have special values that do not map to integers. double.NaN (Not a Number) and double.PositiveInfinity/double.NegativeInfinity cannot be converted to an int in a meaningful way. The direct cast of NaN yields an unspecified value (often int.MinValue), while Convert.ToInt32 throws an OverflowException. For robust code, check for these values before conversion:
if (double.IsNaN(d) || double.IsInfinity(d)) { // handle invalid input }
Large double values also suffer from precision loss when cast to int. A double can represent values up to about 1.8e308, but int only goes up to 2,147,483,647. Even within the int range, a double may not represent every integer exactly due to its 53-bit mantissa. For example, double can exactly represent integers up to 2^53, but beyond that, some integers are skipped. When you cast a double that is very close to an integer boundary, the result may be off by one due to floating-point rounding. This is not a bug in the conversion; it is an inherent property of binary floating-point arithmetic.
Performance and Maintainability Considerations
The direct cast is the fastest conversion because it is a single IL instruction. Convert.ToInt32 adds a method call and a range check, so it is slightly slower. Math.Round and friends involve more complex logic, especially when a MidpointRounding option is specified. For most applications, the performance difference is negligible, but in tight loops that convert millions of values, the cast may be measurably faster.
Maintainability matters more in practice. The cast (int)d silently truncates, which may not be the intent. Convert.ToInt32 clearly signals rounding to the nearest even integer. Math.Floor and Math.Ceiling make the rounding direction explicit. Choose the method that best communicates the behavior you want, so future maintainers do not have to guess.
Choosing the Right Conversion for Your Scenario
The table below summarizes the key differences:
| Method | Rounding Behavior | Overflow Behavior | Best Use Case |
|---|---|---|---|
(int)d | Truncates toward zero | Unchecked (undefined) | Fast truncation when range is known |
Convert.ToInt32(d) | Round half to even | Throws OverflowException | Safe rounding with range validation |
(int)Math.Round(d, mode) | Configurable midpoint | Unchecked (cast) | Explicit rounding strategy |
(int)Math.Floor(d) | Rounds down | Unchecked (cast) | Always round toward negative infinity |
(int)Math.Ceiling(d) | Rounds up | Unchecked (cast) | Always round toward positive infinity |
Use the direct cast when you explicitly want truncation and you are certain the value fits in an int. Use Convert.ToInt32 when you need rounding to the nearest even integer and want overflow protection. Use Math.Round with a MidpointRounding argument when you need a specific midpoint rule, such as AwayFromZero for typical rounding. Use Math.Floor or Math.Ceiling when the direction of rounding is part of the business logic, such as calculating page counts or grid positions.