Почему это не переполнение? - PullRequest
2 голосов
/ 14 июля 2009

Учитывая этот код:

int x = 20000;
int y = 20000;
int z = 40000;

// Why is it printing WTF? Isn't 40,000 > 32,767?
if ((x + y) == z) Console.WriteLine("WTF?");

И зная, что int может содержать от -32,768 до +32,767. Почему это не вызывает переполнение?

Ответы [ 12 ]

21 голосов
/ 14 июля 2009

В C # тип int отображается на тип Int32, который всегда 32-битный, со знаком.

Даже если вы используете short, оно все равно не будет переполнено, потому что short + short возвращает int по умолчанию. Если вы приведете это значение int к short - (short)(x + y) - вы получите переполненное значение. Вы не получите исключения, хотя. Вы можете использовать поведение checked, чтобы получить исключение:

using System;

namespace TestOverflow
{
    class Program
    {
        static void Main(string[] args)
        {
            short x = 20000;
            short y = 20000;
            short z;

            Console.WriteLine("Overflowing with default behavior...");
            z = (short)(x + y);
            Console.WriteLine("Okay! Value is {0}. Press any key to overflow " +
                "with 'checked' keyword.", z);
            Console.ReadKey(true);

            z = checked((short)(x + y));
        }
    }
}

Вы можете найти информацию о checkedunchecked) на MSDN. Это в основном сводится к производительности, потому что проверка на переполнение немного медленнее, чем его игнорирование (и именно поэтому поведение по умолчанию обычно unchecked, но я держу пари, что в некоторых компиляторах / конфигурациях вы получите исключение при первом z назначение.)

10 голосов
/ 14 июля 2009

http://msdn.microsoft.com/en-us/library/5kzh1b5w.aspx

Тип: int Диапазон: от -2 147 483 648 до 2 147 483 647

6 голосов
/ 14 июля 2009

Хотя все правы, говоря, что тип int на 32-битной машине, скорее всего, 2 ^ 32, в вашей методологии есть явный недостаток.

Предположим, что int был 16-битным. Вы присваиваете значение, которое будет переполнять z, поэтому само z переполняется. Когда вы вычисляете x + y, вы также переполняете тип int, очень вероятно, что оба случая переполнятся до одного и того же значения, то есть вы достигнете своего равенства независимо (это, вероятно, зависит от компилятора, я не совсем уверен, х + у будет повышен).

Правильный способ проведения эксперимента: z имеет больший тип данных, чем x и y. Например (извините за простой C, я не очень люблю C #. Надеюсь, что это иллюстрирует методологию.)

int x = INT_MAX;
int y = INT_MAX;
int sum = x + y;
long long z = INT_MAX+INT_MAX;
if(sum == z) 
 printf("Why didn't sum overflow?!\n");

Сравнение суммы и z важно, так как сравнение x + y и z может все же получиться в зависимости от того, как компилятор обрабатывает продвижение.

2 голосов
/ 14 июля 2009

Поскольку int в .NET представляет собой 32-битное число со знаком и диапазоном от -2 147 483 648 до 2 147 483 647 .

Ссылка: http://msdn.microsoft.com/en-us/library/5kzh1b5w(VS.80).aspx

2 голосов
/ 14 июля 2009

В C # Int равен 4 байта. Таким образом, он достигает 2 ^ 31 или 2 147 483 648. Если вы хотите получить 2-байтовое целое число, используйте вместо короткого целого число.

1 голос
/ 14 июля 2009

Прежде всего ваш код находится в диапазоне для int ... Однако, если он не был в диапазоне, то он также не будет жаловаться ... потому что вы никогда не присваиваете значение какой-либо переменной после выполнения X + Y в ваш если проверить ...

Предположим, что если вы выполняете X * Y, тогда оно будет вычислено, и результатом будет длинное значение, тогда значение из переменной Z будет взято и увеличено до long, тогда оба будут сравниваться ... Помните приведение из значение примитива от нижнего диапазона до значения верхнего диапазона неявно.

int x = 200000; //In your code it was 20000
int y = 200000; //In your code it was 20000
int z = 40000;

// Why is it printing WTF? Isn't 40,000 > 32,767?
// Note: X + Y = 200000 and not < 32,767 
// would pass compiler coz you are not assigning and values are compared as longs
// And since it's not equals to 40,000 the WTF did not got printed
if ((x + y) == z) Console.WriteLine("WTF?");     
// And x * y >= z is true WTF MULTIPLY got printed
if ((x * y) >= z) Console.WriteLine("WTF MULTIPLY?"); 
// Compiler would fail since x can't hold 40,00,00,00,000
x = x * y; 
1 голос
/ 14 июля 2009

вам дано напечатать результат как "WTF?" . Затем, как это должно отображать другое значение.

Int означает int32, его диапазон составляет от –2147483648 до 2147483647. Вам дан диапазон от int16: –32768 до 32767

По этой причине не выдается никакой ошибки

1 голос
/ 14 июля 2009

в C # int (System.Int32) имеет 32 бита, которые могут успешно хранить это значение.

1 голос
/ 14 июля 2009

Ключевое слово int соответствует типу .NET Framework Int32 , которое может содержать целые числа в диапазоне от -2 147 483 648 до 2 147 483 647.

1 голос
/ 14 июля 2009

Размер целого - 4 байта, поэтому он может содержать не менее 2 ^ 31, что составляет около 2 млрд.

...