Глиф Учебники

Переполнение int и long long

Справочник · C++ · 2 минуты чтения

int вмещает числа только до 2 147 483 647 (примерно 2,1·10⁹). Если результат больше, int переполняется: ответ становится неверным, часто отрицательным, и никакого сообщения об ошибке нет. Для больших чисел берите long long — до 9 223 372 036 854 775 807 (примерно 9,2·10¹⁸).

C++
#include <iostream>
#include <climits>
using namespace std;

int main() {
    cout << INT_MAX << "\n";
    cout << LLONG_MAX << "\n";
    return 0;
}
Вывод
2147483647
9223372036854775807
ТипНаименьшееНаибольшее
int−2 147 483 6482 147 483 647
long longоколо −9,2·10¹⁸около 9,2·10¹⁸
unsigned long long0около 1,8·10¹⁹

Пределы есть в <climits>: INT_MAX, INT_MIN, LLONG_MAX, LLONG_MIN.

Главная ловушка: умножение

Поменять тип результата недостаточно:

C++
int a = 100000, b = 300000;
long long c = a * b;        // неверно!

a * b считается в типе int, потому что оба множителя — int. Произведение переполняется до того, как попадёт в long long. Нужно, чтобы хотя бы один множитель был long long уже при умножении:

C++
#include <iostream>
using namespace std;

int main() {
    int a = 100000, b = 300000;
    long long c = 1LL * a * b;
    long long d = (long long)a * b;
    cout << c << " " << d << "\n";
    return 0;
}
Вывод
30000000000 30000000000

1LL — единица типа long long; умножение на неё переводит всё выражение в long long. Порядок важен: a * b * 1LL не поможет, потому что a * b уже посчитано в int.

То же со сдвигами (1 << 40 — единица, сдвинутая на 40 двоичных разрядов, то есть 2⁴⁰): 1 << 40 переполняет int, а 1LL << 40 даёт 1 099 511 627 776.

Как понять, что дело в переполнении

Прикидывайте размер ответа заранее: сумма 10⁵ чисел до 10⁹ — это до 10¹⁴, нужен long long; произведение двух чисел до 10⁹ — до 10¹⁸, long long ещё хватает; произведение трёх — уже нет.

Подводные камни

Переполнение знакового целого по правилам C++ — неопределённое поведение: правила языка не говорят, что произойдёт. Обычно число «перескакивает» в отрицательные, но при оптимизации компилятор вправе сделать и что-то неожиданное. Не полагайтесь на него.