Диапазон integer и переполнение
Если сумма, произведение или факториал вдруг получаются отрицательными или странными, число не поместилось в тип переменной. Опишите переменную как longint, а для совсем больших чисел — как int64.
Сколько помещается в каждый тип
| Тип | Диапазон |
|---|---|
byte | 0 … 255 |
word | 0 … 65 535 |
integer в PascalABC.NET | −2 147 483 648 … 2 147 483 647 |
integer в Free Pascal (обычный режим) и Turbo Pascal | −32 768 … 32 767 |
longint | −2 147 483 648 … 2 147 483 647 |
int64 | −9 223 372 036 854 775 808 … 9 223 372 036 854 775 807 |
Главная ловушка — integer. В PascalABC.NET он большой, а в Free Pascal в обычном режиме — всего до 32 767. Программа, которая верно работает в школе, дома в Free Pascal может выдать неверный ответ. longint и int64 одинаковы везде.
Как выглядит переполнение
program Overflow;
var
s, i: integer;
begin
s := 0;
for i := 1 to 1000 do
s := s + i;
writeln(s);
end.Сумма чисел от 1 до 1000 — 500 500. PascalABC.NET так и выведет. Free Pascal в обычном режиме выведет −23 788: число не поместилось в 16 бит, лишние разряды отбросились, и результат «перевалил» в отрицательные. Ошибки при этом нет — программа просто считает неверно. Исправление — s: longint.
Переполнение возможно и в 32 битах: 50 000 · 50 000 = 2,5 миллиарда уже не помещается в longint.
Какой тип выбрать
- Счётчики, номера, индексы массива —
integer. - Суммы, произведения, всё, что может превысить 32 767 —
longint. - Факториалы, степени, произведения больших чисел —
int64. В него помещается до 20!, а вlongint— только до 12!. - Ещё больше — в PascalABC.NET есть тип
BigIntegerдля целых чисел любой длины. В Free Pascal такого встроенного типа нет, длинные числа хранят в массиве цифр и складывают «столбиком».
Подводные камни
- Промежуточный результат. Произведение двух
longintсчитается в 32 битах, даже если его записывают вint64:x := a * bпереполнится при большихaиb. Описывайте какint64и сами множители. - Порядок действий. Для НОК пишите
a div d * b, а неa * b div d: сначала деление, и промежуточное число меньше. real— не спасение. Типrealвмещает огромные числа, но хранит около 15 значащих цифр: младшие цифры большого целого в нём теряются. Для точных целых беритеint64.- Режим Free Pascal. Строка
{$mode objfpc}в начале программы делаетinteger32-битным, но это настройка только Free Pascal. Для программ, которые должны работать везде, проще писатьlongint.