Счёт в программировании начинается с нуля, потому что индекс — это не порядковый номер элемента, а его смещение от начала массива в памяти. Адрес элемента считается по формуле адрес = база + индекс × размер. У самого первого элемента смещение равно нулю: он лежит ровно там, где начинается массив. Поэтому его индекс — 0, а не 1.
Коротко, что стоит за этим правилом:
- Адресная арифметика. Индекс 0 у первого элемента убирает лишнее вычитание при доступе к памяти.
- Полуоткрытые интервалы. Диапазон
0 ≤ i < Nзадаёт массив из N элементов без «+1» и «−1». - Длина = последний индекс + 1. В массиве из 10 элементов последний индекс — 9.
- Срезы и циклы. Половинки диапазона стыкуются встык, длина среза = верхняя граница минус нижняя.
- Не универсальный закон. Fortran, MATLAB, Lua, R и Julia считают с единицы — и работают.
Почему индекс первого элемента — ноль, а не единица

Массив в памяти — это непрерывный кусок ячеек, лежащих подряд. Чтобы обратиться к элементу, процессор должен вычислить его точный адрес. Делается это через смещение от начала.
Если индексация начинается с нуля, формула адреса максимально простая:
адрес(i) = база + i × размер_элемента
// первый элемент: база + 0 × размер = база
// второй элемент: база + 1 × размер
// третий элемент: база + 2 × размер
Индекс здесь буквально отвечает на вопрос «сколько элементов лежит перед этим». Перед первым элементом не лежит ничего — значит, его индекс 0. Перед вторым лежит один элемент — индекс 1. Это не соглашение ради красоты, а прямое отражение того, как данные размещены в памяти.
Если бы отсчёт шёл с единицы, в формулу пришлось бы добавить постоянную поправку:
адрес(i) = база + (i − 1) × размер_элемента
Это лишнее вычитание на каждый доступ к элементу. В языке C, где массивы напрямую связаны с указателями, нулевая индексация даёт более простую реализацию: запись arr[i] — это ровно *(arr + i), то есть «взять то, что лежит по адресу база плюс i». Индекс здесь — смещение от стартовой позиции массива, поэтому у первого элемента смещение равно нулю.
Вывод. Ноль у первого элемента — это следствие того, что индекс измеряет расстояние от начала, а не порядок в человеческом смысле.

- Возможность получить Доступ в Нейроклуб на целый месяц
- Как ИИ ускоряет работу и приносит деньги
- За 2 часа вы получите четкий план, как начать работать с ИИ прямо сейчас!
Заметка Дейкстры: почему это не только про железо
В 1982 году Эдсгер Дейкстра написал короткую заметку EWD831 «Why numbering should start at zero». Он показал, что нулевая индексация выигрывает не только из-за адресной арифметики, но и математически — из-за того, как удобнее записывать диапазоны.
Диапазон целых чисел можно ограничить четырьмя способами, комбинируя ≤ и < на нижней и верхней границе. Дейкстра разбирает все четыре и выбирает полуоткрытый интервал вида a ≤ i < b — включаем нижнюю границу, исключаем верхнюю. Его аргументы:
- Длина считается вычитанием. Число элементов в
a ≤ i < bравно ровноb − a. Никаких «+1». - Пустой диапазон не ломается. Пустая последовательность записывается как
a ≤ i < a. Если бы верхняя граница включалась, при сжатии до пустоты её пришлось бы делать «неестественной» — уходить ниже нижней. - Диапазоны стыкуются встык. Два соседних куска примыкают друг к другу, когда верхняя граница одного равна нижней границе второго. Ни зазора, ни нахлёста.
А дальше — ключевой шаг. Если зафиксировать полуоткрытый интервал a ≤ i < b и спросить, с чего начинать нумерацию массива из N элементов, то старт с единицы даёт диапазон 1 ≤ i < N+1, а старт с нуля — более чистый 0 ≤ i < N. Формулировка Дейкстры: порядковый номер элемента равен числу элементов, стоящих перед ним. Именно это и означает индекс 0 у первого.
Дейкстра ссылался на опыт языка Mesa, где перепробовали остальные три варианта записи диапазонов — и все они оказались источником постоянных мелких ошибок и неуклюжести.
Интуиция: индекс — это этаж, а не порядковый номер
Есть бытовая аналогия, которая снимает первичное непонимание. В британской системе первый этаж дома — это ground floor, «нулевой»: вы стоите на земле, поднялись на 0 пролётов. Следующий этаж — «первый», один пролёт вверх. Число этажа здесь означает не «какой по счёту», а «на сколько выше начала».
Индекс массива устроен так же. arr[0] — это «нулевое смещение от начала», вы никуда не сдвинулись. arr[3] — «сдвинуться на три элемента вправо». Как только перестаёшь читать индекс как «номер по порядку» и начинаешь читать как «на сколько шагов от старта», нулевая нумерация становится единственно логичной.
Вывод. Индекс отвечает на «на сколько дальше от начала», а порядковый номер («первый», «второй») — это уже человеческий перевод, который в C-подобных языках получается прибавлением единицы к индексу.
Что даёт нулевая нумерация на практике
Три вещи, ради которых это соглашение живёт десятилетиями.
Длина и последний индекс связаны без поправок
В массиве из N элементов индексы идут от 0 до N−1, а длина равна N. Последний индекс — это длина − 1. Проверка «вышли ли за границу» — это просто i < length, без сравнения с length − 1.
Модульная арифметика ложится ровно
Когда индексы начинаются с нуля, остаток от деления работает как индекс без сдвига. Классический приём — «закольцевать» массив:
# Python: следующий индекс по кругу
next_i = (i + 1) % len(arr)
# при i = len-1 получаем 0 — вернулись в начало
# при единичной индексации пришлось бы писать
# ((i - 1 + 1) % len) + 1 — лишние сдвиги туда-обратно
Хеш-таблицы, кольцевые буферы, разбивка на N корзин — везде значение % N даёт готовый индекс от 0 до N−1.
Двумерные структуры адресуются проще
Матрицу из R строк по C столбцов в памяти обычно раскладывают в один линейный массив (построчно). Адрес элемента [row][col] считается так:
смещение = row × C + col
// row=0, col=0 → 0 (самое начало)
// row=1, col=0 → C (начало второй строки)
// row=2, col=3 → 2×C + 3
С нулевой индексацией формула чистая и без поправок. При единичной пришлось бы писать (row − 1) × C + (col − 1) с двумя вычитаниями. Чем больше измерений, тем заметнее выигрыш.
Циклы пишутся одинаково
Стандартный цикл по массиву в C-подобных языках выглядит так:
for (int i = 0; i < n; i++) {
// arr[i] — от первого до последнего
}
Верхняя граница i < n — это тот самый полуоткрытый интервал Дейкстры. Число итераций равно n, читается с одного взгляда.
Вывод. Нулевая индексация убирает поправки «плюс-минус один» из формул длины, из модульной арифметики и из условий циклов.
Языки, которые считают с единицы
Нулевая индексация — не физический закон, а инженерный выбор. Часть языков осознанно считает с единицы, потому что их проектировали ближе к математике и предметной области, а не к адресам памяти. Сравнение:
| Язык | Первый индекс | Почему так |
|---|---|---|
| C, C++, Java, Python, JavaScript, C#, Go, Rust | 0 | Индекс = смещение от начала, близость к указателям |
| Fortran | 1 (по умолчанию) | Язык под математику; нижнюю границу можно задать вручную |
| COBOL | 1 | Соответствие обычным порядковым номерам |
| MATLAB | 1 | Матрицы и векторы как в линейной алгебре |
| R | 1 | Статистика, работа с таблицами данных |
| Lua | 1 (идиоматично) | Таблицы принято нумеровать с 1 |
| Julia | 1 | Ориентация на научные вычисления |
| Pascal, Ada | Любой | Нижнюю границу диапазона задаёт программист |
Вывод простой: если пишете на языке, где принято с единицы, спорить с ним не нужно. Проблемы начинаются, когда переносят привычку из одного языка в другой без проверки.
Off-by-one: главная ошибка на нулевой индексации
Ошибка «на единицу» (off-by-one) — самая частая цена нулевой нумерации. Возникает там, где путают «длину» и «последний индекс».
# Ошибка: выход за границу массива
arr = [10, 20, 30, 40, 50] # длина 5, индексы 0..4
for i in range(len(arr) + 1): # 0,1,2,3,4,5 — лишняя 5
print(arr[i]) # IndexError на i = 5
Последний валидный индекс — len(arr) − 1, то есть 4. Обращение к arr[5] вылетает за пределы. Обратная версия ошибки — начать цикл с 1 и потерять первый элемент.
Практические ориентиры, которые снимают большинство таких промахов:
- Последний индекс — всегда
длина − 1, а недлина. - В условии цикла держите
i < длина, а неi <= длина. - Число элементов в
a ≤ i < b— этоb − a. Если считаете длину и получаете «на единицу больше», проверьте границу.
Вывод. Off-by-one лечится не осторожностью, а привычкой держать в голове полуоткрытый интервал: нижняя граница включена, верхняя — нет.
Связь со срезами
Срезы (slices) — прямое продолжение той же логики. В Python arr[a:b] берёт элементы с индекса a включительно до b не включая — тот самый полуоткрытый интервал.
arr = [10, 20, 30, 40, 50]
arr[0:2] # [10, 20] — длина 2 − 0 = 2
arr[2:5] # [30, 40, 50] — длина 5 − 2 = 3
arr[2:2] # [] — пустой срез, a = b
Из-за исключённой верхней границы срезы стыкуются без нахлёста: arr[0:2] и arr[2:5] вместе дают весь массив, элемент с индексом 2 не задваивается. Длина среза считается вычитанием границ, а пустой срез arr[2:2] не требует особой обработки. Ровно те три свойства, которые Дейкстра выписал для полуоткрытого интервала, — они и работают в срезах каждый день.
FAQ
С какого числа начинается счёт в программировании?
В большинстве распространённых языков (C, C++, Java, Python, JavaScript, C#, Go, Rust) индексация массивов начинается с нуля: первый элемент имеет индекс 0. Но это не всеобщее правило — Fortran, MATLAB, R, Lua и Julia считают с единицы.
Почему первый элемент массива имеет индекс 0?
Потому что индекс — это смещение от начала массива в памяти, а не порядковый номер. Первый элемент лежит в самом начале, его смещение равно нулю. Формула адреса база + индекс × размер для него даёт просто база.
Что такое ошибка off-by-one?
Это промах на единицу при работе с границами: обращение к arr[длина] вместо arr[длина − 1], лишняя или недостающая итерация цикла. Частая причина — путаница между длиной массива и индексом последнего элемента.
Почему массив из N элементов имеет индексы от 0 до N−1?
Потому что диапазон индексов — полуоткрытый: 0 ≤ i < N. Всего значений ровно N, они идут от 0 до N−1. Длина массива при этом равна N, а последний индекс — N−1.
Все ли языки считают с нуля?
Нет. Нулевая индексация доминирует в C-подобных и веб-языках, но Fortran, COBOL, MATLAB, R, Lua и Julia используют единичную. Pascal и Ada позволяют задать нижнюю границу диапазона вручную. Это инженерное соглашение, а не закон.
Обновлено в 2026 году. Первоисточник аргументации о полуоткрытых интервалах — заметка Дейкстры EWD831.
- Выполним базовые задачи на российских нейросетях и посмотрим на результаты!
- Файл-инструкцию «Как сделать нейро-фотосессию из своего фото бесплатно, без иностранных карт и прочих сложностей»
- Покажем 10+ способов улучшить свою жизнь с ИИ каждому — от ребенка и пенсионера до управленца и предпринимателя
- Возможность получить Доступ в Нейроклуб на целый месяц
- Как ИИ ускоряет работу и приносит деньги
- За 2 часа вы получите четкий план, как начать работать с ИИ прямо сейчас!