2016-05-25 15 views
5

Я сейчас читаю книгу о программировании на C#, и у нее есть краткое введение в Overflow и Underflow, и автор дает общее представление о том, что происходит, когда вы переходите через допустимый диапазон определенного типа.Может кто-нибудь объяснить переполнение в C# с помощью двоичного?

Пример

short a = 30000; 
short b = 30000; 
short sum = (short)(a + b); // Explicitly cast back into short 
Console.WriteLine(sum); // This would output the value -5536 

Поэтому короткий тип только имеет диапазон от -32768 до 32767, и в книге объяснение, данное автором является «для целочисленных типов (байт, короткие, Int, и длинный), наиболее значимые биты (которые переполняются) отбрасываются. Это особенно странно, поскольку компьютер затем интерпретирует его как обертывание. Вот почему в нашем примере мы получаем отрицательное значение. Вы можете легко это увидеть, если вы начинаете с максимального значения для определенного типа (например, short.MaxValue) и добавляете его к нему ». В # Игроки C Руководство Второе издание, глава 9, стр 58

Вы бы в конечном итоге на минимуме (-32768).

У меня проблема с пониманием этого я запутаться, когда писатель говорит о «компьютер интерпретирует его как обтекание»

так, как я пытался это понять, что короткий тип использует 2 байта (16 бит)

таким образом, число 32767 = 0111111111111111 , если я был +1 к двоичной строке я бы в конечном итоге с 32768 = 1000000000000000 (которые не могут быть представлены с коротким типом, как максимальное значение равно 32767), так что компилятор дает -32768. Почему это отрицательно?

Я понимаю концепцию использования дополнения twos для представления отрицательных чисел, и кто-то может исправить мое мышление здесь или разработать, потому что я не совсем понимаю, почему мы используем только 15 бит из 16 бит для представления положительного диапазона и наиболее Значительный бит для отрицательного диапазона

+1

Вы забываете учитывать бит знака. –

+0

Я не понимаю :(, не могли бы вы объяснить, пожалуйста? – Shabubble

+0

При знаках со знаком один бит (MSB) зарезервирован в качестве знакового бита, чтобы указать, является ли число положительным или отрицательным. Как еще вы могли бы узнать, был отрицательным или нет? Вы не считаете, что этот бит должен присутствовать. –

ответ

16

Игнорировать всех, кто говорит вам, что верхний бит является знаковым битом. Это неправильный способ подумать об этом.

Правильный способ думать о нем:

  • У нас есть 65536 возможных битовых комбинаций.
  • Поэтому мы можем представить 65536 возможных номеров.
  • У нас должна быть карта, которая назначает , что означает для каждого битового рисунка.

Для беззнаковых трусах, мы относим битовые шаблоны следующим образом:

0000000000000000 --> 0 
0000000000000001 --> 1 
... 
0111111111111111 --> 32767 
1000000000000000 --> 32768 
1000000000000001 --> 32769 
... 
1111111111111111 --> 65535 

Для подписал шорты, мы используем следующее соглашение:

0000000000000000 --> 0 
0000000000000001 --> 1 
... 
0111111111111111 --> 32767 
1000000000000000 --> -32768 
1000000000000001 --> -32767 
... 
1111111111111111 --> -1 

просто.

Почему мы используем это соглашение?

Три причины:

(1) Первые 32K значения одинаковы ли вы подписаны или без знака. Это очень удобно.

(2) В обоих условностях «все нулевые разряды» означают ноль.

(3) Потому что добавление работает точно так же в обеих условностях!

Мы

0000000000000000 --> 0 

и мы хотим, чтобы добавить один. Мы добавляем один, используя двоичные правила, и получаем:

0000000000000001 --> 1 

Это работает независимо от того, подписан ли короткий или нет.

Мы беззнаковое короткое:

1000000000000000 --> 32768 

Мы хотели бы добавить один. Мы делаем это с использованием двоичных правил, и мы получаем правильный ответ:

1000000000000001 --> 32769 

То же самое касается подписанных шорт. У нас есть

1000000000000000 --> -32768 

и мы хотим его добавить. Мы делаем это с бинарными правилами, и мы получаем:

1000000000000001 --> -32767 

Кроме того, вы можете проверить, что при добавлении 1111111111111111 к любому двоичного числа, вы получите «один меньше», и, следовательно, вычитание одной работы, а также добавлением одного , Затем вы можете показать, что в целом сложение и вычитание работают одинаково как в арифметике с подписью, так и без знака, что означает . Процессор не должен знать, компилятор считает, что значения подписаны или неподписанные.

Вот почему мы используем два дополнения: потому что базовая математика точно такая же, независимо от того, выполняете ли вы арифметику со знаком или без знака.

Обратите внимание, что я ничего не сказал о «знаке». Тот факт, что высокий бит задан для отрицательных чисел, является просто хорошим бонусом. Мы хотим, чтобы мы только строили оборудование, чтобы делать математику раз.

Компонент Twos - это - просто соглашение о назначении одного из двух возможных значений битовых шаблонов на основе типа, связанного с переменной, содержащей этот битовый рисунок. Как отрасль, мы выбрали это соглашение, потому что дешево производить высокопроизводительное оборудование, использующее это соглашение.

Существует множество других конвенций, которые мы могли бы выбрать. Например, мы могли бы сказать, что для чисел со знаком мы используем карту:

0000000000000000 --> -32768 
0000000000000001 --> -32767 
... 
0111111111111111 --> -1 
1000000000000000 --> 0 
1000000000000001 --> 1 
... 
1111111111111111 --> 32767 

Обратите внимание, что это точно такой же, как и раньше для старшего бита, за исключением!

В этой интерпретации дополнение по-прежнему работает, как и ожидалось. Но эта карта не обладает тем свойством, что первые 32K-значения являются одинаковыми между short и ushort и не обладают тем свойством, что все нулевые биты равны нулю. Поэтому мы не используем это соглашение, потому что это менее удобно. В этом соглашении преобразование от короткого к ushort потребует добавления. Установка короткого замыкания на ноль требует установки байтов на что-то отличное от нуля. Мы могли бы использовать соглашение, где подписанные числа были «в порядке», мы просто не делаем этого, потому что это больно.

+0

Хорошее объяснение дает больше смысла :) У меня возникли проблемы с пониманием «Первые 32K-значения одинаковы независимо от того, подписаны ли вы или нет». – Shabubble

+0

Подождите, я думаю, что знаю 1000000000000000 -> 32768 и 1000000000000000 -> -32768 имеют один и тот же бит-шаблон, я не видел этого до – Shabubble

+0

@Shabubble: Что такое бит-шаблон для 123 в подписанном коротком? Что такое битовый шаблон для 123 в беззнаковом коротком? Они одинаковые. На самом деле они все одинаковые, вплоть до 32767. –