Сложение в обратных кодах
Случай 1. А и В положительные числа.
При суммировании таких чисел просто складываются их обратные коды (которые равны прямым), включая знаковый разряд. Учитывая тот факт, что у положительных чисел знаковый разряд равен нулю, у суммы он также равен нулю, следовательно, число получается положительное.
1310 = 0000 11012 (ПК/ОК)
2310 = 0001 01112 (ПК/ОК)
(13+23)10 = 0010 01002 (ПК/ОК) = 3610
Случай 2. А — положительное, а В — отрицательное, по модулю больше А.
В этом случае мы просто складываем числа А и В. Результат получаем, как обычно, в обратном коде:
1310 = 0000 11012 (ПК/ОК)
−2310 = 1001 01112 (ПК) = 1110 10002 (ОК)
(13 + (−23))10 = 1111 01012 (ОК) = 1000 10102 (ПК) = −1010
Случай 3. А — положительное, а В — отрицательное, по модулю меньше А.
На первый взгляд, кажется, что этот случай не отличается от рассмотренного выше второго, однако, давайте посмотрим, что же получится в итоге:
−1310 = 1000 11012 (ПК) = 1111 00102 (ОК)
2310 = 0001 01112 (ПК)
Обратите внимание на результат. У нас выходит, будто сумма — отрицательное число (ибо в знаковом разряде единица), причем, цифр также больше. И, даже если бы не будем учитывать знак, а просто переведем модуль, то получим 910, а не 1010, как должно быть.
Компьютер решает эту проблему, прибавляя получившуюся «лишнюю» единицу к получившемуся числу. Выглядит это следующим образом:
Как видите, в результате мы получили положительное число 0000 10102, переведя которое в десятичную систему счисления мы получим 1010. А это и есть правильный ответ.
Случай 4. А и В отрицательные числа.
При таких условиях нам точно так же, как и в третьем случае, придется прибавлять единицу из знакового разряда к основному числу.
Проверим:
−1310 = 1000 11012 (ПК) = 1111 00102 (ОК)
−2310 = 1001 01112 (ПК) = 1110 10002 (ОК)
Переведем получившийся обратный код в десятичное число: 1101 10112 (ОК) = 1010 01002 (ПК) = −3610. Как мы видим, ответ получился верным.
Однако, не всегда сложение проходит так гладко. Если вдруг числа у нас достаточно большие, то может возникнуть переполнение, то есть, результат не будет помещаться в выделенное для него место в памяти. Как вам понять, что возникло переполнение? Конечно, можно перевести число в десятичную систему счисления и проверить, больше ли модуль этого числа, чем максимально возможный. Однако, есть и другой способ. Если знак результата получается не таким, какой вы ожидали (не такой, как в примерах выше), значит, произошло переполнение.
К слову, «максимально возможный модуль» для чисел со знаком равен 2n-1, где n — количество бит, отведенных для хранения числа. Напомню, что в 1 байте 8 бит, в 2 байтах 16 бит и так далее. Получается, что если на хранение числа у вас отводится один байт, то максимально возможный модуль это 28-1 = 27 = 128. Если число у вас получается по модулю больше, значит, для операции требуется выделить на слагаемые больше памяти.
Отмечу, что переполнение может возникнуть только в том случае, когда оба числа положительны или отрицательны, ибо, когда знаки у них разные, модуль результата будет меньше как минимум одного слагаемого.
Случай 5. Переполнение, когда А и В положительные.
10010 = 0110 01002 (ПК/ОК)
3010 = 0001 11102 (ПК/ОК)
Заметьте, что, складывая два положительных числа, мы получили отрицательное. Следовательно — переполнение. Решается это, как я уже говорил, расширением диапазона:
10010 = 0000 0000 0110 01002 (ПК/ОК)
3010 = 0000 0000 0001 11102 (ПК/ОК)
Обратите внимание, что теперь в старшем разряде у нас 0, а значит, получили мы положительное число. И, естественно, результат верен: 0000 0000 1000 00102 = 13010.
Случай 6. Переполнение, когда A и B — отрицательные.
Тут та же история, что и в пятом случае. Убедимся в этом:
-10010 = 1110 01002 (ПК) = 1001 10112 (ОК)
-3010 = 1001 11102 (ПК) = 1110 00012 (ОК)
Как обычно, убираем лишнюю единицу, прибавляя ее к результату:
Итог: положительное число. Что делаем? Расширяем диапазон!
-10010 = 1000 0000 0110 01002 (ПК) = 1111 1111 1001 10112 (ОК)
-3010 = 1000 0000 0001 11102 (ПК) = 1111 1111 1110 00012 (ОК)
На этот раз получается отрицательное число. Значит, все верно.
