views:

12105

answers:

9

How do I convert a decimal to an int?

Ta

+30  A: 

Use Convert.ToInt32 from mscorlib as in

decimal value = 3.14m;
int n = Convert.ToInt32(value);

See MSDN. You can also use Decimal.ToInt32. Again, see MSDN. Finally, you can do a direct cast as in

decimal value = 3.14m;
int n = (int) value;

which uses the explicit cast operator. See MSDN.

Jason
+4  A: 

System.Decimal implements the IConvertable interface, which has a ToInt32() member. Does calling System.Decimal.ToInt32() work for you?

Andy
+4  A: 
 decimal d = 2;
 int i = (int) d;

Works just fine

luiscubal
Careful, with an explicit conversion information might be lost.
Phaedrus
When converting from decimal to int, information will almost always be lost but I believe that's kinda the point.
Dinah
+3  A: 
int i = (int)d;

will give you the number rounded down.

If you want to round to the nearest even number (i.e. >.5 will round up) you can use

int i = (int)Math.Round(d, MidpointRounding.ToEven);

In general you can cast between all the numerical types in C#. If there is no information that will be lost during the cast you can do it implicitly:

int i = 10;
decimal d = i;

though you can still do it explicitly if you wish:

int i = 10;
decimal d = (decimal)i;

However, if you are going to be losing information through the cast you must do it explicitly (to show you are aware you may be losing information):

decimal d = 10.5M;
int i = (int)d;

Here you are losing the ".5". This may be fine, but you must be explicit about it and make an explicit cast to show you know you may be losing the information.

ICR
A: 

A neat trick for fast rounding is to add .5 before you cast your decimal to an int.

decimal d = 10.1m;
d += .5m;
int i = (int)d;

Still leaves i=10, but

decimal d = 10.5m;
d += .5m;
int i = (int)d;

Would round up so that i=11.

DeadlyBrad42
Why bother doing this when there's Math.Floor and Math.Ceiling?
Badaro
At the time, I was fairly new to C# and for some reason I didn't realize these functions existed. It's actually a trick I learned from C/C++, where it was obviously more useful.
DeadlyBrad42
+13  A: 

You can't.

Well, of course you could, however an int (System.Int32) is not big enough to hold every possible decimal value.

That means if you cast a decimal that's larger than int.MaxValue you will overflow, and if the decimal is smaller than int.MinValue, it will underflow.

What happens when you under/overflow? One of two things. If your build is unchecked (i.e., the CLR doesn't care if you do), your application will continue after the value over/underflows, but the value in the int will not be what you expected. This can lead to intermittent bugs and may be hard to fix. You'll end up your application in an unknown state which may result in your application corrupting whatever important data its working on. Not good.

If your assembly is checked (properties->build->advanced->check for arithmetic overflow/underflow or the /checked compiler option), your code will throw an exception when an under/overflow occurs. This is probably better than not; however the default for assemblies is not to check for over/underflow.

The real question is "what are you trying to do?" Without knowing your requirements, nobody can tell you what you should do in this case, other than the obvious: DON'T DO IT.

If you specifically do NOT care, the answers here are valid. However, you should communicate your understanding that an overflow may occur and that it doesn't matter by wrapping your cast code in an unchecked block

unchecked
{
  // do your conversions that may underflow/overflow here
}

That way people coming behind you understand you don't care, and if in the future someone changes your builds to /checked, your code won't break unexpectedly.

If all you want to do is drop the fractional portion of the number, leaving the integral part, you can use Math.Truncate.

decimal actual = 10.5M;
decimal expected = 10M;
Assert.AreEqual(expected, Math.Truncate(actual));
Will
Though I suspect they're the same thing under the hood if the input is a decimal, I feel more comfortable using Decimal.Truncate than Math.Truncate, since the latter also accepts doubles and thus can be understood to be able to truncate even numbers that are not base 10, as opposed to Decimal.Truncate, which is a true truncation of a base 10 number.
Brian
Unchecked contexts do not apply to decimals; operations on decimals will throw OverflowExceptions regardless.
Dave
@dave Damnit, you're right. BRB, ECMA.
Will
+1  A: 

I prefer using Math.Round, Math.Floor, Math.Ceiling or Math.Truncate to explicitly set the rounding mode as appropriate.

Note that they all return Decimal as well - since Decimal has a larger range of values than an Int32, so you'll still need to cast (and check for overflow/underflow).

 checked {
   int i = (int)Math.Floor(d);
 }
Mark Brackett
A: 

I find that the casting operator does not work if you have a boxed decimal (i.e. a decimal value inside an object type). Convert.ToInt32(decimal as object) works fine in this case.

This situation comes up when retrieving IDENTITY/AUTONUMBER values from the database:

SqlCommand foo = new SqlCommand("INSERT INTO...; SELECT SCOPE_IDENTITY()", conn);
int ID = Convert.ToInt32(foo.ExecuteScalar());  // works
int ID = (int)foo.ExecuteScalar();              // throws InvalidCastException

See 4.3.2 Unboxing conversions

Timbo
A: 

decimal d = 5.5;

int i = decimal.ToInt32(d);// you will get i = 5

ref: link text

__w