Исключение переполнения для int в С#?
У меня был этот странный опыт с проблемой номер 10 на Project Euler (отличный сайт, кстати). Задача состояла в том, чтобы вычислить сумму всех простых чисел ниже двух миллионов.
Я использовал int для суммы, и мой алгоритм дал ответ, но когда я вставил его, чтобы проверить ответ, это было неправильно.
Оказалось, что результат слишком велик, чтобы вписаться в int, но не может ли это вызвать ошибку переполнения или что-то еще? Вместо этого он просто вернул значение, далекое от реального ответа.
Когда я сменил тип на длинный, все было hunky dory.
Ответы
Ответ 1
Операции с целыми числами С# не перебрасывают исключения при переполнении по умолчанию. Это можно выполнить с помощью настроек проекта или путем расчета checked
:
int result = checked(largeInt + otherLargeInt);
Теперь операция будет выбрана.
Противоположность unchecked
, что делает любую операцию явно непроверенной. Очевидно, это имеет смысл только тогда, когда вы включили проверенные операции в настройках проекта.
Ответ 2
В С# a OverflowException
не выбрасывается (в VB исключение выбрасывается по умолчанию).
Чтобы получить excpetion, вам нужно встроить свой код в контекст 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; в С# они не являются. Если операция происходит в неконтролируемом контексте, результат усекается, отбрасывая любые биты высокого порядка, которые не вписываются в тип назначения.
Ответ 3
Это потому, что по умолчанию С# не генерирует никакого исключения для переполнения целого числа, а также для нижнего потока. Здесь вы можете сделать пару вещей.
Вариант 1
Вы должны разрешить исключение, переходя к
Project = > properties = > Вставить вкладку = > Дополнительно = > проверить арифметическое переполнение потока (убедитесь, что вы отметили опцию)
![enter image description here]()
Удостоверьтесь, что вы отметили опцию
Вариант 2
Использовать отмеченный блок и исключить исключение переполнения для обработки ситуации. Пример фрагмента кода будет
try
{
checked
{
int y = 1000000000;
short x = (short)y;
}
}
catch (OverflowException ex)
{
MessageBox.Show("Overflow");
}
catch (Exception ex)
{
MessageBox.Show("Error");
}
Надеюсь, это поможет вам...:)
Ответ 4
Я уже добавил cmt, но это может быть интересно для некоторых из вас:
msdn сообщает нам:
Целочисленное арифметическое переполнение либо выбрасывает исключение OverflowException или отбрасывает наиболее значимые биты результат
но
Десятичное арифметическое переполнение всегда выдает исключение OverflowException.
и
Когда происходит переполнение целых чисел, что происходит, зависит от исполнения контекст, который можно проверить или бесконтрольно. В проверенном контексте Вызывается исключение OverflowException. В неконтролируемый контекст, наиболее Значительные биты результата отбрасывается и исполнение продолжается. Таким образом, С# дает вам выбор обработки или игнорирования переполнения.
Ответ 5
По умолчанию С# не проверяет арифметическое переполнение целых чисел. Вы можете изменить это с помощью параметра /checked
компилятора или включив "Проверка арифметического переполнения/недополнения" в Visual Studio (свойства проекта - Build - Advanced).
Вы можете использовать checked
и unchecked
ключевые слова, чтобы переопределить значение по умолчанию в каждом конкретном случае. Если вы полагаетесь на проверку, выполняемую в куске кода, явным образом разрешаю использовать его с помощью checked
. Это хорошая идея.
int j = checked(i * 2);
checked
{
int j = i * 2;
// Do more stuff
}
Обратите внимание, что операции с плавающей запятой никогда не выбрасывают OverflowException
, а десятичные операции всегда вызывают OverflowException
. См. Также Операторы С#.