我在Project Euler(顺便说一句,很棒的网站)上遇到了第10号问题的奇怪经历。任务是计算低于200万的所有素数之和。
我使用了一个int作为总和,我的算法产生了一个答案,但是当我粘贴它来验证答案时,这是错误的。
事实证明,结果太大而不适合int,但这不会导致溢出错误或其他什么?相反,它只返回了一个远离真实答案的值。
当我将类型更改为long时,一切都很笨拙。
答案 0 :(得分:85)
默认情况下,C#整数操作在溢出时不会抛出异常。您可以通过项目设置或计算checked
:
int result = checked(largeInt + otherLargeInt);
现在操作将抛出。
相反的是unchecked
,这使得任何操作都明确取消选中。显然,只有在项目设置中启用了检查操作时,这才有意义。
答案 1 :(得分:19)
在C#中,不抛出OverflowException
(在VB中,默认情况下抛出异常)。
要获得重复,您必须将代码嵌入checked
上下文中:
byte value = 241;
checked
{
try
{
sbyte newValue = (sbyte) value;
Console.WriteLine("Converted the {0} value {1} to the {2} value {3}.",
value.GetType().Name, value,
newValue.GetType().Name, newValue);
}
catch (OverflowException)
{
Console.WriteLine("Exception: {0} > {1}.", value, SByte.MaxValue);
}
}
MSDN更详细地解释:
算术,铸造或 转换操作抛出一个 OverflowException,操作必须 发生在检查的上下文中。通过 默认,算术运算和 检查Visual Basic中的溢出; 在C#中,它们不是。如果操作 发生在未经检查的上下文中 通过丢弃任何结果来截断结果 不适合的高阶位 目的地类型。
答案 2 :(得分:14)
这是因为,默认情况下,C#不会抛出整数溢出和下溢的任何异常。你可以在这里做几件事。
选项1
您必须通过转到启用异常 项目=> properties =>构建标签=>高级=>检查算术溢出下溢。(确保勾选选项)
确保勾选选项
选项2
使用选中的块并抛出溢出异常来处理这种情况。示例代码段将是
try
{
checked
{
int y = 1000000000;
short x = (short)y;
}
}
catch (OverflowException ex)
{
MessageBox.Show("Overflow");
}
catch (Exception ex)
{
MessageBox.Show("Error");
}
希望这会对你有所帮助...... :)
答案 3 :(得分:7)
我已经添加了一个cmt,但对于你们中的一些人来说这可能很有趣:
msdn告诉我们:
整数算术溢出 抛出OverflowException或 抛弃最重要的部分 结果
但
始终为十进制算术溢出 抛出OverflowException。
也
当整数溢出时,什么 发生取决于执行 上下文,可以检查或 选中。在检查的上下文中, 抛出OverflowException。在一个 未经检查的背景,最多 结果的重要部分是 丢弃并继续执行。 因此,C#为您提供了选择 处理或忽略溢出。
答案 4 :(得分:6)
默认情况下,C#不检查整数上的算术溢出。您可以使用/checked
compiler option或在Visual Studio中启用“检查算术溢出/下溢”(项目属性 - 构建 - 高级)来更改此项。
您可以根据具体情况使用checked
and unchecked
keywords覆盖默认值。如果您依赖于在一段代码中进行检查,则使用checked
明确启用它将是一个好主意。
int j = checked(i * 2);
checked
{
int j = i * 2;
// Do more stuff
}
请注意,浮点运算从不抛出OverflowException
,十进制运算总是抛出OverflowException
。另请参阅C# operators。
答案 5 :(得分:0)
我有一个数学运算被截断而不会产生错误,即使目标是一个大变量:
Int count1 = (1000*10000) x 1024; //an exception is not raised
或
即使目标变量很大,它仍然会被截断并且不会抛出任何异常,我不明白为什么 count2
被视为 int32
而不是 int64
Int64 count2 = (1000*10000) x 1024;
注意:10000 是从配置文件中读取的变量