Вопрос с собеседования · Основы
Что происходит при переполнении целого числа?
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 в бинарном поиске
Подробно
Целое фиксированной ширины хранит 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++ — компилятор может её удалить.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗В Java и Go переполнение int бросает исключение ArithmeticException, а в Python int переполняется на 2⁶³
- ✓В Java и Go результат молча заворачивается по модулю 2ⁿ: MAX_VALUE + 1 = MIN_VALUE
- ✗В Python int переполняется при 2⁶³
- ✗Переполнение знаковых целых в C всегда заворачивается
Что спросят дальше
- Как работает бинарный поиск? Junior
Связанные вопросы
Партнёр платформы
Разбор собеседования
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.