Почему int.MaxValue - int.MinValue = -1?
Насколько я понимаю, это должно привести к ошибке переполнения и когда я напишу его следующим образом:
public static void Main()
{
Console.WriteLine(int.MaxValue - int.MinValue);
}
он правильно дал мне ошибку переполнения.
Однако:
public static void Main()
{
Console.WriteLine(test());
}
public static Int32 test(int minimum = int.MinValue, int maximum = int.MaxValue)
{
return maximum - minimum;
}
будет выводиться -1
Почему он это делает? Он должен выкинуть ошибку, потому что ее явно переполнение!
Ответы
Ответ 1
int.MaxValue - int.MinValue
= значение, которое int не может удерживать. Таким образом, число обертывается назад до -1.
Это как 2147483647 - (- 2147483648) = 4294967295, который не является int
Поле Int32.MinValue
Значение этой константы -2,147,483,648;, то есть шестнадцатеричный 0x80000000.
И Поле Int32.MaxValue
Значение этой константы 2 147 483 647, то есть шестнадцатеричное 0x7FFFFFFF.
От MSDN
Когда происходит переполнение целых чисел, что происходит, зависит от выполнения контекст, который можно проверить или снять. В проверенном контексте Вызывается исключение OverflowException. В неконтролируемом контексте наиболее значимые биты результата отбрасываются и выполнение продолжается. Таким образом, С# дает вам выбор обработки или игнорирования переполнения.
Ответ 2
Это происходит из-за проверки переполнения кода во время компиляции. Строка
Console.WriteLine(int.MaxValue - int.MinValue);
на самом деле не будет ошибкой во время выполнения, он просто напишет "-1", но из-за проверки переполнения вы получите ошибку компиляции "Операция переполняется во время компиляции в режиме проверки".
Чтобы обойти проверку переполнения времени компиляции в этом случае, вы можете:
unchecked
{
Console.WriteLine(int.MaxValue - int.MinValue);
}
Что будет нормально работать и вывести "-1"
Ответ 3
По умолчанию для уровня проекта на уровне проекта установлено значение "unchecked" по умолчанию. Вы можете включить проверку переполнения, перейдя к свойствам проекта, вкладке "Сборка", "Дополнительно". Всплывающее окно позволяет включить проверку переполнения. Инструмент .NET Fiddle, с которым вы ссылаетесь, кажется, выполняет некоторый дополнительный статический анализ, который мешает вам видеть истинное поведение в режиме реального времени. (Ошибка для вашего первого фрагмента кода выше: "Операция переполняется во время компиляции в режиме проверки". Вы не видите ошибку времени выполнения.)
Ответ 4
Я думаю, что это происходит даже дальше, чем переполнение.
если я посмотрю на это
Int64 max = Int32.MaxValue;
Console.WriteLine(max.ToString("X16")); // 000000007FFFFFFF
Int64 min = Int32.MinValue;
Console.WriteLine(min.ToString("X")); //FFFFFFFF80000000
Int64 subtract = max - min;
Console.WriteLine(subtract.ToString("X16")); //00000000FFFFFFFF <- not an overflow since it a 64 bit number
Int32 neg = -1
Console.WriteLine(neg.ToString("X")); //FFFFFFFF
Здесь вы видите, что если вы просто вычтите шестнадцатеричные значения) в 2 дополнениях, вы получите число -1 в 32-битном номере. (после транкинга ведущего 0
2 арифметики дополнения могут быть очень забавными http://en.wikipedia.org/wiki/Two 's_complement