Здравствуй, дорогой читатель. Сегодня хочется поразмышлять над одной странной фразой: один плюс один равно ноль. Буднично за такое можно получить вопросительный взгляд. А в мире информационных технологий это совершенно нормальный результат. Давайте разбираться без страшной математики: сначала лампочки и выключатели, потом биты и перенос.
Небольшой дисклеймер: это новое прочтение Автором его же собственной старой статьи «1+1=0! Как считает компьютер?». Смысл остался прежним, но объяснение стало спокойнее, нагляднее и ближе к нынешнему стилю канала.
Вечер с восемью лампочками
Представьте кухонный стол. Илья принес коробку с восемью лампочками и подписал их слева направо: 1, 2, 4, 8, 16, 32, 64, 128. Алиса смотрит на это как на настольную игру.
Компьютер внутри не видит красивую десятичную запись, а видит состояния - биты. Поэтому для наглядности мы будем использовать состояния лампочки. Горит — 1. Не горит — 0.
Арина тем временем нажимает выключатель у первой лампочки. Она не знает слова "бит", зато прекрасно понимает "свет горит". И это, дорогой читатель, почти вся основа цифрового мира.
Восемь лампочек — это восемь бит. Вместе они могут показать числа от 0000 0000 до 1111 1111. То есть от 0 до 255. Больше в такую коробку не помещается.
Если хочется сначала спокойно разобраться, почему 10 в двоичной системе — это не десять, а два, у Автора уже есть отдельная статья: «Что такое системы счисления? Простыми словами». Здесь мы не будем заново проходить всю теорию, а сразу посмотрим, как компьютер складывает такие записи. А в статье уже рассказано, почему 1111 1111 - это 255.
Как складывать свет
Илья предлагает Алисе сложить два маленьких числа. Например:
0000 0011 и 0000 0001.
— Это три плюс один? — уточняет Алиса.
— Да. Смотрим справа налево, как при сложении в столбик.
Если в одном разряде получается 0 + 1, лампочка суммы горит: это 1. Если 1 + 0, тоже 1. Если 0 + 0, не горит: 0.
А вот 1 + 1 уже интереснее. В обычной десятичной системе мы знаем: 9 + 1 дает 0 в текущем разряде и переносит 1 в следующий. В двоичной системе похожая история: 1 + 1 = 10. В текущей лампочке остается 0, а в следующую уходит перенос 1.
Где появляется 1+1=0
Теперь Илья ставит все восемь лампочек во включенное состояние:
1111 1111
— Это 255, максимум для нашей коробки, — говорит он.
Алиса добавляет один:
0000 0001
Начинаем справа. 1 + 1 дает 0 и перенос. В следующем разряде снова получается 1 + перенос, опять 0 и новый перенос. Так перенос бежит через всю коробку, как маленькая волна.
В конце он хочет зажечь девятую лампочку. Но девятой лампочки нет (картинка ниже).
Арина смотрит на пустое место за коробкой и честно показывает пальцем:
— Нету.
Вот именно. Если мы заранее договорились, что у нас только 8 бит, то лишний девятый разряд просто не помещается. Внутри коробки остается:
0000 0000
Так и получается: при 8-битном сложении 255 + 1 = 0.
Как это работает на самом деле
В техническом языке лампочки — это биты. Бит хранит одно из двух значений: 0 или 1. Несколько бит образуют число. Если битов 8, получается 8-битное целое с 256 возможными комбинациями.
Важно: 256 комбинаций — это не числа от 1 до 256, а состояния от 0000 0000 до 1111 1111. Если считать без знака, это числа от 0 до 255.
Когда компьютер складывает двоичные числа, он делает то же, что мы в столбик:
- складывает младший разряд;
- записывает результат в текущий разряд;
- переносит лишнюю единицу в следующий;
- повторяет, пока разряды не закончатся.
Если перенос вышел за границу доступных разрядов, возникает переполнение. В некоторых системах оно просто обрезается. В других система замечает это и ставит специальный флаг ошибки или переполнения. Смысл один: число не поместилось в отведенное место.
Где мы встречаем это в жизни
Такое ограничение есть не только в старых учебных примерах. Любая программа работает с числами определенного размера: 8, 16, 32, 64 бита. Обычно современные языки и системы помогают не наступать на такие ошибки, но принцип никуда не исчез.
В счетчиках, таймерах, играх, датчиках и старых программах переполнение может давать странные эффекты: число внезапно перескакивает к нулю, счетчик начинает идти "с начала", значение становится отрицательным или программа ведет себя неожиданно.
Что может пойти не так
Главная ошибка — думать, что компьютер "просто ошибся в арифметике". Нет. Он честно выполнил сложение по правилам, но результат не поместился.
Вторая ошибка — забывать, что один и тот же набор битов можно понимать по-разному. 1111 1111 может быть 255, если число без знака. А в другом соглашении это может означать -1. Компьютер хранит биты, а смысл им задают правила программы.
Третья ошибка — считать, что сегодня переполнение уже не бывает. Бывает. Просто чаще оно спрятано глубже: в драйверах, низкоуровневом коде, форматах файлов, счетчиках и старых протоколах.
Мифы
Миф: компьютер считает в десятичной системе, просто показывает нам двоичную.
На самом деле: внутри цифровых схем удобнее работать с двумя состояниями: есть сигнал или нет сигнала.
Миф: 1 + 1 = 0 означает ошибку компьютера.
На самом деле: в ограниченной 8-битной коробке это может быть ожидаемый результат после переполнения.
Миф: чем больше память компьютера, тем больше любое число.
На самом деле: размер оперативной памяти и размер конкретного числового типа — разные вещи.
Миф: переполнение касается только древних компьютеров.
На самом деле: современные системы тоже учитывают границы чисел, просто делают это аккуратнее.
Итог
Запомнить можно так: компьютер считает лампочками. Каждая лампочка — один бит. Восемь лампочек дают коробку от 0 до 255. Если к максимальному значению добавить 1, перенос хочет уйти в девятую лампочку, но ее нет. Внутри остается ноль.
Илья закрывает коробку, Алиса уже не спорит с арифметикой, а Арина радостно выключает все лампочки сразу. Для нее это игра. Для компьютера — строгие правила хранения чисел.
UPD
Автор упростил несколько деталей. В реальных процессорах сложением занимаются логические схемы, а не лампочки на столе. Переполнение может обрабатываться по-разному: игнорироваться, фиксироваться специальным флагом, вызывать ошибку или предотвращаться языком программирования.
Также бывают числа со знаком и без знака, разные способы представления отрицательных чисел и разные размеры типов. Но базовая картинка остается верной: двоичное число должно поместиться в выделенное количество бит.