Исключение переполнения для 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. См. Также Операторы С#.