Получить доступ

Что происходит при переполнении целого числа?

JuniorЧисла в компьютере
Ещё спрашивают так:
  • Чему равно Integer.MAX_VALUE + 1?
  • Почему в бинарном поиске пишут low + (high - low) / 2?
  • Есть ли переполнение в Python?
Коротко

Результат не влезает в разрядность — в Java, Go, C# он молча заворачивается по модулю 2ⁿ: MAX_VALUE + 1 = MIN_VALUE.

  • В C и C++ переполнение знаковых — неопределённое поведение
  • В Python int неограничен, переполнения нет (кроме numpy)
  • Защита: Math.addExact, проверка до операции, тип пошире

А ещё Классика — (low + high) / 2 в бинарном поиске

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Попробуйте сами

Число изнутри: дополнительный код и плавающая точка

Подробно

Целое фиксированной ширины хранит n бит. Если результат операции требует больше, лишние старшие биты отбрасываются, и число «заворачивается» — это арифметика по модулю 2ⁿ. В дополнительном коде это значит, что Integer.MAX_VALUE + 1 даёт Integer.MIN_VALUE: из 0111…1 получается 1000…0.

Как ведут себя языки:

  • Java, C#, Go, Kotlin — заворачивание, без исключения. В Java есть Math.addExact, multiplyExact, toIntExact — они бросают ArithmeticException; в C# — блок checked;
  • C и C++ — для знаковых переполнение — неопределённое поведение: компилятор вправе считать, что его не бывает, и, например, выкинуть проверку if (x + 1 < x). Беззнаковые заворачиваются по определению;
  • Rust — в отладочной сборке паника, в релизной заворачивание; есть checked_add, wrapping_add, saturating_add;
  • Python — int произвольной длины, переполнения нет. Но в numpy и pandas типы фиксированные (int64), там заворачивание есть.

Где ловит на практике:

  • середина в бинарном поиске: (low + high) / 2 переполняется на больших массивах — эта ошибка годами жила в стандартной библиотеке Java. Пишут low + (high - low) / 2 или (low + high) >>> 1;
  • сравнение через вычитание: return a - b в компараторе ломается, если a большое положительное, а b большое отрицательное. Правильно — Integer.compare(a, b);
  • время в миллисекундах в int: 2³¹ мс — всего 24,8 суток;
  • умножение размеров: width * height * 4 для большой картинки;
  • счётчики и идентификаторы: автоинкремент int в базе кончается на 2,1 млрд строк.

Пример

int x = Integer.MAX_VALUE;
System.out.println(x + 1);              // -2147483648
System.out.println(Math.abs(Integer.MIN_VALUE)); // -2147483648
Math.addExact(x, 1);                    // ArithmeticException

int mid = (low + high) >>> 1;           // безопасная середина

Что хотят услышать

  • Заворачивание по модулю и почему MAX + 1 = MIN.
  • Различия языков: Java тихо, C/C++ UB, Python без ограничений.
  • Хотя бы один практический пример: середина бинарного поиска или компаратор.
  • Как защищаться: *Exact-методы, тип шире, проверка заранее.

Частые ошибки

  • Ожидать исключение в Java при обычном +.
  • Проверять переполнение после операции в C/C++ — компилятор может её удалить.

Что спросят дальше

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем