С чего начинать индексацию массива — с нуля или с единицы? :) |
||
|
МЕНЮ Главная страница Поиск Регистрация на сайте Помощь проекту Архив новостей ТЕМЫ Новости ИИ Голосовой помощник Разработка ИИГородские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Искусственный интеллект Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Нейронные сети начинающим Психология ИИ Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Творчество ИИ Техническое зрение Чат-боты Авторизация |
2023-10-04 14:51 За этим детским вопросом скрываются фундаментальные нюансы программирования. Большинство современных языков выбирают ноль (потому что почти все они, кроме Python, своим синтаксисом вышли из Си). Но например мультипарадигмальный язык Julia выбрал единицу — этот выбор ортогонален мэйнстриму, и я могу легко изменить в нём начало отсчёта на 0 по желанию. Почему для трека "Как понять в программировании всё" я выбрал Julia => https://vk.com/wall-152484379_3499 Причина обсуждения такого тривиального вопроса заключается в том, что это очень яркий пример того, как выбор, имевший смысл на заре программирования полвека назад и больше, сегодня неплохо бы пересмотреть. Более того, такой вроде бы второстепенный момент затрагивает некоторые принципы проектирования, в частности, абстрактные типы данных. Моя цель — научить тому, как как можно проще программировать большие и сложные системы, а для этого очень важно уменьшать когнитивные усилия на ум программиста там, где это возможно (встраивать думательные машинки, избегая медленного мышления S2 по Канеману прежде всего в теме применения абстракций, а это очень трудно). В человеческой культуре, в нашем языке, и даже в математике глубоко укоренилось представление о том, что счет вещей начинается с единицы. Мы постоянно говорим, что что-то "первое", а не "нулевое". Математики описывают множества как 1...n, а не 0...n-1. Поэтому начинающих программистов нулевая индексация поначалу удивляет. Использование различных соглашений в различных контекстах - это не только одноразовые затраты на обучение, но и постоянные когнитивные издержки. Мне постоянно приходится помнить, что для получения последнего элемента нужно вычесть единицу из длины. Эти маленькие кусочки потерянного внимания невелики, но они возрастают, и мы не можем позволить себе тратить их впустую. Напомню, корень нулевой индексации в том, что Си исходно разрабатывался прежде всего как кросс-платформная замена ассемблеру самых разных ЭВМ, а в ассемблере вы адресуете (указываете) память с нуля, т.к. адрес — это просто сдвиг относительно блока/страницы памяти. Поэтому самый первый байт блока, естественно, имеет сдвиг 0 байтов по отношению к началу. Пиша на Си, вы буквально пишете на "универсальном" ассемблере, складывая и вычитая такие сдвиги (указатели), и этот код очень-очень здорово оптимизируется и транслируется в ассемблер чуть ли не 1:1 (арифметика указателей). Но и тучи ошибок вроде бесконечных бесконтрольных выходов за допустимые границы массивов всегда будут с вами. Но в нормальном языке высокого уровня нету никакой арифметики указателей! Так почему же нулевая индексация так распространена? = Эдсгер Дейкстра отстаивал идею нулевого индексирования. https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.html Во-первых, он утверждает, что интервалы целых чисел должны быть заданы в виде first <= i < last+1 Затем он утверждает, что индексы массива "красивее" выглядят так: 0 <= i < length, а не 1 <= i < length+1 Если честно, раньше мы все тогда так делали, во многом потому, что обучение программированию нередко начиналось с ассемблера, который считался совсем "простым", а вот универсальные языки вроде Фортрана, PL/I, а потом Си и Паскаля были гораздо "сложнее" (в некотором смысле так и есть). Тут можно погрузиться в абстрактный интерфейс к типу данных "интервал", который должен обладать, по крайней мере, свойствами first, last и length. Тогда мы можем построить интервал, указав любые два из этих свойств, но для этого нам нужен очень "буквальный" синтаксис вроде first...last (как было сделано в Паскале). Дейкстра также хотел ещё свойство next, которое на 1 больше last. И как только мы получили правильно абстрагированные интервалы, выбор начального индекса становится произвольным. Диапазон индексов массива длины n с равным успехом может быть как 0..n-1, так и 1..n. = Массивы, по сути, имитируют матрицы и векторы в математике, в которой до начала компьютерной эры, и во многих случаях до сих пор используются индексы, основанные на 1. В Matlab, как и в большинстве матриц и векторов, используется 1-ориентированная индексация. В языках Паскаль и Ада индексация может быть произвольной: вы хотите индексировать массив от -7 до +7... нет проблем. Да, некоторые виды манипуляций с массивами проще выполнять с помощью нулевой индексации, и в определённых обстоятельствах она позволяет получить более чистый код. Причина, по которой многим людям нравится индексация с нуля, исключительно в том, что они просто привыкли программировать на Cи-подобных языках, где такая индексация считается нормой, т.к. пришла из фактически из ассемблера. Гвидо ван Россум обосновывал индексацию с нуля в Python исключительно тем, что его "смутила элегантность полуоткрытых интервалов" ("swayed by the elegance of half-open intervals"). Но сколько ошибок в мире было совершено из-за того, что программисты сбивались на единичку, когда делали слайсы a[:i] или a[i:j], забывая, что i:j подразумевает диапазон i .. j-1 ? = Сермяга в том, что, правильно абстрагировав интервалы, мы можем точно определить различие между индексами и длинами, и инкапсулировать арифметику, связывающую их. Все эти операции наподобие ++ и — на самом деле жёсткие преобразования, которые должны быть абстрагированы. Таким образом, нет никаких веских причин для выбора нулевого индексирования. Ведь нам гораздо естественнее вести отсчёт с единицы. Нам давно пора покончить с наследием ассемблера в современном программировании. P.S. Мне кажется, что некоторый энтузиазм в отношении нулевого индексирования проистекает из интеллектуального тщеславия. "Посмотрите на меня: Я такой умный, что считаю не так, как обычные люди". А для начинающих программистов 0-ориентированная индексация — это огромная проблема с точки зрения удобства. Массив состоит из 10 элементов, но 1-й элемент на самом деле 0-й, а 10-й - 9-й (помните споры, с какого года начался 21-й век?). Математически ориентированные языки, такие как Matlab, Фортран и Julia, допускают индексацию с 1. Каждому своё. Кому-то нравится 0-ориентированная индексация, а кому-то - 1-ориентированная. Возможно, правильного ответа нет... и, может быть, немного дополнительной работы мозга в языках с 1-ориентированным индексом — не такая уж плохая вещь. Источник: skillsmart.ru Комментарии: |
|