我很好奇将double转换为int的最佳方法。运行时安全是我的主要关注点(它不一定是最快的方法,但这将是我的次要问题)。我已经留下了一些我可以在下面提出的选项。任何人都可以权衡哪种是最佳做法?我还没有列出任何更好的方法来实现这个目标吗?
double foo = 1;
int bar;
// Option 1
bool parsed = Int32.TryParse(foo.ToString(), out bar);
if (parsed)
{
//...
}
// Option 2
bar = Convert.ToInt32(foo);
// Option 3
if (foo < Int32.MaxValue && foo > Int32.MinValue) { bar = (Int32)foo; }
答案 0 :(得分:25)
我认为你最好的选择是:
checked
{
try
{
int bar = (int)foo;
}
catch (OverflowException)
{
...
}
}
来自Explicit Numeric Conversions Table
“当您从double或float值转换为整数类型时,该值将被截断。如果生成的整数值超出目标值的范围,则结果取决于溢出检查上下文。在选中的上下文中,抛出OverflowException,而在未经检查的上下文中,结果是目标类型的未指定值。“
注意:Option 2在需要时也会抛出OverflowException
。
答案 1 :(得分:6)
我更喜欢选项2。
您需要做的一件事是检查异常但确认它有效,就像您在选项1中检查'已解析'一样:
try
{
bar = Convert.ToInt32(foo);
}
catch(OverflowException)
{
// no can do!
{
如果你要转换字符串等而不是double,你可能会得到一个'FormatException'。
修改强>
我最初说选项2并不比选项1特别好,@ 0xA3指出错误。选项1更糟糕,因为它在被解析为整数之前转换为字符串,这意味着效率较低。如果double超出整数范围(您可能想要或可能不想要),也不会得到OverflowException - 虽然在这种情况下'parsed'将为False。
答案 2 :(得分:5)
我意识到这不是OP要求的,但这个信息可能很方便。
以下是比较(来自http://www.dotnetspider.com/resources/1812-Difference-among-Int-Parse-Convert-ToInt.aspx)
string s1 = "1234";
string s2 = "1234.65";
string s3 = null;
string s4 = "12345678901234567890123456789012345678901234567890";
int result;
bool success;
result = Int32.Parse(s1); // 1234
result = Int32.Parse(s2); // FormatException
result = Int32.Parse(s3); // ArgumentNullException
result = Int32.Parse(s4); // OverflowException
result = Convert.ToInt32(s1); // 1234
result = Convert.ToInt32(s2); // FormatException
result = Convert.ToInt32(s3); // 0
result = Convert.ToInt32(s4); // OverflowException
success = Int32.TryParse(s1, out result); // 1234
success = Int32.TryParse(s2, out result); // 0
success = Int32.TryParse(s3, out result); // 0
success = Int32.TryParse(s4, out result); // 0
答案 3 :(得分:3)
我会使用选项二。简短,干净,有效。
你也可以查看.Net4中的BigInteger类,你不必检查溢出。
double foo = 1;
BigInteger bigint = new BigInteger(foo);
答案 4 :(得分:3)
我总是使用Convert类,我发现它非常优雅,方便,你可以捕获VS intellisense中定义的特定异常。
答案 5 :(得分:3)
选项3a不使用例外,总是返回一个值:
Int32 Convert(Double d)
{
if (d <= (double)Int32.MinValue)
return Int32.MinValue;
else if (d >= (double)Int32.MaxValue)
return Int32.MaxValue;
else
return (Int32)d;
}
答案 6 :(得分:2)
选项(1)和(2)基本上做同样的事情。选项(1)为您提供if (parsed)
块,而选项(2)则为double
无法表示的任何int
引发错误。
选项(3)与选项(2)基本相同,除了它有额外的MinValue
/ MaxValue
检查,而其他选项则没有。
总结:这三段代码做了不同的事情。选项(3)看起来是最强大的,因为它有一个额外的范围检查。
修改:再想一想,使用@Ani checked
技巧 - 您可以免费获得范围检查。
答案 7 :(得分:2)
如果您确实需要查明是否出现问题,请使用正常演员并检查结果。
int ToInt(double foo)
{
int result = (int)foo;
if (foo != result)
throw new ArgumentException()
return result;
}
这将确保不会进行无效转换。如果可以舍入到最接近的整数,请使用Math.Round
并检查结果是否在0.5之内。这将确保您的方法无法获得NaN或无穷大。