如何在C#中将十进制转换为整数?

266

我该如何将十进制转换为整数?


13
请问您是想将数据四舍五入至最接近的整数,还是直接舍去小数部分(例如:总是向下取整)?知道这一点会更有帮助。 - Dinah
13个回答

323

可以使用mscorlib中的Convert.ToInt32,例如:

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

参见MSDN。您还可以使用Decimal.ToInt32。同样,参见MSDN。最后,您可以进行直接转换,如:

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

使用显式类型转换运算符。请参阅MSDN


10
注意:在某些转换情况下,Convert 方法会有一些意外的行为(例如 null vs. 0 vs. "")。建议您不要使用 Convert 方法,除非您绝对需要它的灵活性(例如在动态类型的场景下)。 - Eamon Nerbonne
1
-1 因为这对于 decimal.MaxValue 和 decimal.MinValue 等值不起作用,并导致 OverflowException。我认为 @Will 在这里提供了更好的答案 https://dev59.com/C3RB5IYBdhLWcg3wz6ed#501165。 - mezoid
11
注意,因为Convert.ToInt32Decimal.ToInt32的行为不同。根据MSDN文档:Decimal.ToInt32的返回值是十进制数值的整数部分;小数位被截断。Convert.ToInt32的返回值将舍入到最接近的32位有符号整数。如果值处于两个整数之间,则返回偶数;例如4.5被转换为4,而5.5被转换为6。 - vezucci

69

不行。

当然,你可以,但是 int (System.Int32) 不足以容纳每个可能的十进制值。

这意味着,如果你转换一个大于 int.MaxValue 的十进制数,你将会溢出,如果小于 int.MinValue,则会下溢。

当你下/上溢时会发生什么?有两种情况。如果你的构建未经检查(即 CLR 不关心你是否这样做),则在值溢出/下溢后,你的应用程序将继续运行,但 int 中的值将不是你期望的值。这可能导致间歇性错误,并且可能很难修复。你的应用程序最终处于未知状态,可能导致应用程序破坏其正在处理的任何重要数据。这不好。

如果你的程序集已经检查过了(属性->生成->高级->检查算术溢出/下溢或 /checked 编译器选项),当发生下/上溢时,你的代码将抛出异常。这可能比不检查更好;然而,程序集的默认设置是不检查溢出/下溢。

实际问题是“你要做什么?”如果不知道您的要求,除了显而易见的“不要这样做”,没有人能告诉您在这种情况下应该做什么。
如果您确切地不关心,这里的答案是有效的。但是,您应该通过将转换代码包装在块中来表达您已经知道可能会发生溢出,但这并不重要。
unchecked
{
  // do your conversions that may underflow/overflow here
}

这样做可以让后来的人知道你并不在意,如果将来有人将你的构建更改为/checked,你的代码也不会意外地崩溃。

如果你只想舍弃数字的小数部分,保留整数部分,你可以使用Math.Truncate。

decimal actual = 10.5M;
decimal expected = 10M;
Assert.AreEqual(expected, Math.Truncate(actual));

3
虽然我怀疑如果输入是十进制数,它们在内部是相同的东西,但我更喜欢使用Decimal.Truncate而不是Math.Truncate,因为后者还接受双精度浮点数,因此可以理解为能截断不是十进制的数字,而Decimal.Truncate则是真正截断十进制数字。 - Brian
8
未经检查的上下文不适用于十进制数;对十进制数的操作将引发 OverflowExceptions 异常。 - Dave

50
int i = (int)d;

该函数将向下取整到最接近的整数。

如果你想要四舍五入到最接近的偶数(例如:>.5会向上舍入),你可以使用

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

总的来说,在C#中,你可以在所有数字类型之间进行强制类型转换。如果在转换过程中不会丢失信息,那么你可以隐式地进行类型转换:

You can cast between all numerical types in C#, implicitly if there is no loss of information during the conversion.

int i = 10;
decimal d = i;

如果你愿意,尽管你仍然可以显式地这样做:

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

然而,如果您要通过转换丢失信息,则必须明确指定(以显示您已经意识到可能会丢失信息):

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

在这里,你正在损失 ".5"。 这可能没问题,但你必须明确表达并进行显式转换以显示你知道可能会丢失信息。


1
根据我的经验,如果您希望> *.5始终向上舍入,则实际上需要使用MidpointRounding.AwayFromZero。请参考此处的示例输出:https://msdn.microsoft.com/en-us/library/system.midpointrounding(v=vs.110).aspx#Anchor_2 - Elijah Lofgren
@ElijahLofgren 这有点取决于情况:如果你在做统计,ToEven 应该可以防止统计漂移。但是如果你处理的是可收费物品或金钱,AwayFromZero 似乎是正确的选择。 - mbx

26
decimal d = 2;
int i = (int) d;

这应该完全没问题。


1
小心,使用显式转换可能会丢失信息。 - Phaedrus
21
将十进制转换为整数时,几乎总会丢失信息,但我认为这正是它的意图。 - Dinah

18

8

System.Decimal 实现了 IConvertable 接口,该接口具有一个 ToInt32() 成员。

您能否调用 System.Decimal.ToInt32()


2
文档中可以看到:“此 API 支持 .NET Framework 基础结构,不建议直接从您的代码中使用。” 为什么不使用 Convert.ToInt32? - H.Wolper

8
将十进制数四舍五入到最接近的整数
decimal a ;
int b = (int)(a + 0.5m);

a = 49.9 时,b = 50

a = 49.5 时,b = 50

a = 49.4 时,b = 49 等等。


7

十进制数 d = 5.5;

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

ref: link text


7
一个快速取整的小技巧是在将小数转换为整数之前先加上0.5。
decimal d = 10.1m;
d += .5m;
int i = (int)d;

仍然有i=10,但是

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

将会四舍五入,使得i=11


5
既然有 Math.Floor 和 Math.Ceiling,为什么还要这样做呢? - Badaro
当时,我对C#还比较陌生,出于某种原因,我没有意识到这些函数的存在。实际上,这是我从C/C++中学到的技巧,在那里它显然更有用。 - DeadlyBrad42
1
如果十进制值为-9.3怎么办? - supercat

7
我更喜欢使用 Math.Round, Math.Floor, Math.CeilingMath.Truncate 来明确设置适当的舍入模式。请注意,它们都返回 Decimal - 因为 Decimal 比 Int32 具有更大的值范围,所以您仍需要进行转换(并检查溢出/下溢)。
 checked {
   int i = (int)Math.Floor(d);
 }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接