Почему нулевые массивы являются нормой?

A вопрос, заданный здесь , напомнил мне дискуссию, которую я имел с другим программистом. Он утверждал, что массивы с нулевым основанием должны быть заменены массивами одного типа, поскольку массивы, основанные на нуле, являются деталями реализации, которые возникают из-за того, как работают массивы и указатели и компьютерное оборудование, но такие вещи не должны отражаться на более высоком уровне языки.

Теперь я не очень хорош в обсуждении, поэтому я не мог предложить никаких веских оснований придерживаться нулевых массивов, отличных от того, что они считают более подходящими. Почему является нулевой общей отправной точкой для массивов?

112 голосов | спросил 6 revs, 2 users 45%
Tamas Czinege
1 Jam1000000amThu, 01 Jan 1970 03:00:00 +030070 1970, 03:00:00

30 ответов


105

Я не думаю, что любой из нас может стать более веским аргументом, чем статья Эдсгера У. Дейкстры

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
80

Аргумент полномочий

Ну ... По-видимому, большинство языков, включая очень недавние, основаны на нуле. Поскольку эти языки были написаны довольно опытными людьми, ваш друг должен быть неправ ...

Почему один?

почему 1 был бы лучшим начальным индексом, чем ноль? Почему бы не 2 или 10? Ответ сам по себе интересен тем, что он показывает много о том, как процесс людей защищает идею.

Аргумент first заключается в том, что это более естественно, потому что 1st обычно один , прежде чем все остальные, по крайней мере, для большинства людей ...

Аргумент number- one заключается в том, что последний индекс также является размером массива ...

Меня все еще впечатляет «качество» причин, которые я обычно слышу для таких аргументов ... И даже больше, когда мне напоминают, что ...

Почему не ноль?

... «Одиночные» обозначения оставлены от западной культуры, которые игнорировали существование нуля на протяжении веков, если не больше.

Верьте или нет, исходный грегорианский календарь идет от -3, -2, -1, 1, 2, 3 ... Попробуйте представить проблему, которую он внес в западную науку (например, сколько лет с 1-го 2 января - 1 января 2, чтобы увидеть, чем исходный gregorian calendar конфликтует с чем-то простым, как вычитание ...).

Сохранение массивов на основе одного типа (как бы то ни было, я буду смиренным для этого ... ^ _ ^ ...), держась в милях и ярдах в 21 веке ...

Почему Zero? Потому что это математика!

Сначала (OOops ... Извините ... Я попробую еще раз)

Zero , Zero - ничто, это что-то. И некоторые религиозные тексты утверждают, что «в начале ничего не было». Некоторые дискуссии, связанные с компьютером, могут быть столь же горячими, как и религиозные дебаты, поэтому этот вопрос не так из темы, как кажется ... ^ _ ^

Сначала . Легче работать с нулевым массивом и игнорировать его нулевое значение, чем работать с одним массивом и взломать его, чтобы найти нулевое значение. Эта причина настолько же глупа, как и предыдущая, но тогда исходный аргумент в пользу массивов на основе одного из них также был ошибочным.

Второй . Вспомним, что, имея дело с цифрами, шансы высоки, вы будете заниматься математикой в ​​тот или иной момент, а когда вы занимаетесь математикой, шансы хороши, вы не в настроении для глупых хаков, чтобы обойти устаревшие соглашения. Однозначная нотация преследовала математику и даты на протяжении веков, и, изучая наши ошибки, мы должны стремиться избегать ее в будущих ориентированных науках (включая компьютерные языки).

Третий . Что касается привязки к компьютерным языковым массивам аппаратного обеспечения, выделите массив C из 21 целых чисел и переместите указатель 10 индексов вправо, и у вас будет естественный [-10 до 10]. Это не является естественным для аппаратного обеспечения. Но это для математики. Конечно, математика может быть устаревшей, но в последний раз, когда я проверял, большинство людей в мире полагало, что это не так.

Четыре . Как уже указывалось в другом месте, даже для дискретного положения (или расстояния, сведенного к дискретным значениям) первый индекс будет равен нулю, как пол в здании (начиная с нуля), уменьшая обратный отсчет (3, 2, 1, ZERO!), высоту земли, первый пиксель изображения, температуру (ноль Кельвина, для абсолютного нуля или нуля стоградусного градуса, как температура замораживания воды 273 K). Фактически, единственное, что действительно начинается с одного, - это традиционный способ « сначала , второй , третий и т. Д."). итерация , что приводит меня естественно к точке next ...

Пятая точка next (которая, естественно, следует за предыдущей ), заключается в доступе к контейнерам высокого уровня, а не по индексу, но с помощью итераторов , если сами индексы не имеют внутренней стоимости. Я удивлен, что ваш сторонник на более высоком уровне не упомянул об этом. В случае важности самого индекса вы можете сделать ставку в половине случаев, когда у вас есть вопрос, связанный с математикой. И, таким образом, вы хотите, чтобы ваш контейнербыть математически-дружественным, а не математически-инвалидным, как «ваш старый gregorian calendar», начинающийся с 1, и нуждающийся в срыгивании хаков, чтобы заставить его работать.

Заключение

Аргумент, заданный вашим коллегой-программистом, является ошибочным, поскольку он бесполезно связывает привычки разговорного /письменного языка, которые по своей природе размыты, на компьютерные языки (где вы не хотите, чтобы ваша инструкция была размыта) и потому, что приписывая ошибочно аппаратную причину этой проблемы, он надеется убедить вас, поскольку языки идут все выше и выше в абстракции, что нулевой массив ушел в прошлое.

Нулевые массивы основаны на нулевом уровне из-за причин, связанных с математикой. Не для аппаратных причин.

Теперь, если это проблема для вашего коллеги-программиста, попросите его начать программирование с реальными конструкциями высокого уровня, такими как итераторы и петли foreach.

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
47

Полуоткрытые интервалы составляют хорошо. Если вы имеете дело с 0 <= i < lim, и вы хотите расширить элементы n, новые элементы имеют индексы в диапазоне lim <= i < lim + n. Работа с массивами с нулевым значением упрощает арифметику , когда разделяет или объединяет массивы или когда подсчитывает элементы . Можно надеяться, что более простая арифметика приведет к меньшему количеству ошибок fencepost .

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
29

Некоторые типы манипуляций с массивами становятся сумасшедшими, сложными с массивами на основе 1, но остаются проще с массивами на основе 0.

В какой-то момент я сделал некоторое программирование численного анализа. Я работал с алгоритмами для управления сжатыми, разреженными матрицами, написанными как в FORTRAN, так и в C ++.

Алгоритмы FORTRAN имели много a[i + j + k - 2], а C ++ - a[i + j + k], потому что Массив FORTRAN был основан на 1, а массив C ++ - на основе 0.

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
22

Индекс в массиве не является индексом. Это просто смещение, которое является расстоянием от начала массива. Первый элемент находится в начале массива, поэтому нет расстояния. Поэтому смещение равно 0.

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
17

Причины не только исторические: C и C ++ все еще существуют и широко используются, а арифметика указателей - очень веская причина для запуска массивов с индексом 0.

Для других языков, не имеющих арифметики указателей, является ли первый элемент индексом 0 или 1 скорее соглашением, чем чем-либо еще.
Проблема в том, что языки, которые используют индекс 1 в качестве своего первого элемента, не существуют в вакууме и, как правило, должны взаимодействовать с библиотеками, которые часто записываются внутри - вы уже догадались - C или C ++ ...

VB и его производные ароматы пострадали от того, что массивы начинаются либо с 0 или 1, и это долгое время является источником проблем.

Нижняя строка: не имеет значения, что ваш язык рассматривает индекс первого элемента, если он согласован во всем. Проблема состоит в том, что рассмотрение 1 как первого индекса затрудняет работу на практике.

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
10

Матрицы с нулевым значением имеют свои корни в C и даже ассемблере. С C, указатель math в основном работает следующим образом:

  • Каждый элемент массива занимает определенное количество байтов. 32-битное целое число (очевидно) 4 байта;
  • Адрес массива занят первым элементом массива с последующими элементами в последовательных блоках равного размера после этого.

Чтобы проиллюстрировать, предположим, что int a[4] находится в 0xFF00, адреса:

  • a [0] -> 0xFF00;
  • a [1] -> 0xFF04;
  • a [2] -> 0xFF08;
  • a [3] -> 0xFF0C.

Итак, с нулевыми индексами, addres математика проста:

Адрес элемента = Адрес массива + индекс * sizeof (тип)

Действительно, выражения в C эквивалентны:

    а [2]; 2 [а]; и * (а + 2).

С одними массивами математика (когда-либо) немного сложнее.

Таким образом, причины в основном исторические.

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
8

Если вы используете массивы с нулевым основанием, длина массива - это набор действительных индексов. По крайней мере, это то, что говорит арифметика Пеано:

0 = {}
1 = 0 U {0} = {0}
2 = 1 U {1} = {0,1}
3 = 2 U {2} = {0,1,2}
...
n = n-1 U {n-1} = {0,1,2...n-1}

Так что это естественная нотация, в некотором смысле.

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
7

Поскольку существует сильная корреляция между массивами и указателями в C

char* p = "hello";
char q[] = "hello";

assert(p[1] == q[1]);

assert(*p == *q)

* p совпадает с * (p + 0)

, имеющий начальный индекс 1, даст вам головную боль позже

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
5

Куча является одним из примеров преимуществ массивов на 1 основе. Учитывая индекс i , индекс родительского и левого дочерних элементов i

PARENT [ i ] = i à · 2

LCHILD [ i ] = i Ã-2

Но только для массивов на основе 1. Для массивов на основе 0 у вас есть

PARENT [ i ] = ( i + 1) Ã · 2 - 1

LCHILD [ i ] = ( i + 1) Ã-2 - 1

И тогда у вас есть свойство, что i также является размером подматрицы для этого индекса (т. е. индексы в диапазоне [1, i ]).

Но в конце это не имеет значения, потому что вы можете сделать массив на основе 0 в массиве 1, выделив еще один элемент, чем обычно, и игнорируя нуль. Таким образом, вы можете отказаться от преимуществ массивов на основе 1, когда это необходимо, и сохранить массивы на основе 0 для более чистой арифметики практически во всех других ситуациях.

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
4

Я чувствую, что это совершенно произвольно. Нет ничего особенного в массивах с нулевым или одним массивом. Поскольку я освобождаюсь от Visual Basic (в основном, иногда я делаю крошечные вещи в Excel), я не работал с массивами на основе 1 и ... это то же самое. Дело в том, что если вам нужно третий элемент массива, это всего лишь деталь реализации, которая называется 3 или 2. Однако 99% работы, которую вы делаете с массивами, интересуются только двумя абсолютными точками: первым элементом и числом или длиной . Опять же, это просто деталь реализации, что первый элемент называется нулем вместо одного или последний элемент называется count-1 или вместо него count.

Изменить: . Некоторые из респондентов упомянули, что массивы на основе 1 более подвержены ошибкам fencepost. По моему опыту, думая об этом сейчас, это правда. Я помню, что думал в VB: «Это будет работать или взорваться, потому что я ушел один». В Java никогда не бывает. Хотя я думал, что улучшаюсь, некоторые из респондентов указывают на случаи, когда массивы на основе 0 приводят к лучшей арифметике, ДАЖЕ, когда вам не нужно иметь дело с языком более низкого уровня.

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
4

Как программист на 10 + год C /C ++, имеющий очень сильный фон в Pascal и Delphi, я еще пропустил проверку массивного массива Pascal и проверку типа индекса, а также гибкость и безопасность, которые приходят с Это. Очевидным примером этого являются значения хранения данных массива за каждый месяц.

Паскаль:

 Type Month = (Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec);

  Var Days[Month] of integer;

  ... 
  if Year mod 4 = 0 then // yes this is vastly simplified for leap years and yes i don't know what the comment marker is in pascal and no i won't go look it up
    Days[Feb] := 29
  else
    Days[Feb] := 28;

Написание аналогичного кода на языках C без использования +/- 1 или «магических чисел» довольно сложно. Обратите внимание, что выражения типа Days [2] и Days [Jan + Dec] просто не будут компилироваться, что может оказаться жестоким для людей, которые все еще думают на C или Assembler.

Я должен сказать, что есть много аспектов языков Pascal /Delphi, которые я не пропустил немного, но C-массивы с нулевым значением кажутся просто «немыми» по сравнению.

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
4

Причина, по которой он начинается с 0, а не 1, заключается в том, что вы можете думать о смещении как о том, насколько далеко от начала памяти массива этот элемент. Это не говорит, дайте мне 0-й элемент - это говорит, дайте мне элемент, который является 0 элементами с самого начала.

Другой способ взглянуть на это состоит в том, что они (по большей части) эквивалентны:

array[n]

*(array + n)

Причина, по которой стандарт никогда не будет изменен, заключается в том, что C существует около 40 лет. Нет никаких веских оснований для его изменения, и если бы они это сделали, весь существующий код, который зависит от начала массива, равного 0, будет нарушен.

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
4

Код, содержащий некоторую исходную информацию о местоположении /относительной позиции, намного чище с массивами, начинающимися с 0.

Например: Код для копирования вектора в определенном месте в более крупном векторе - это боль с массивами, начиная с 1:

function copyAtPos (dest, vect, i):
    for i from 1 -> vect.length do
        dest[pos+i-1] = vect[i]

Противоречием с массивами, начинающимися с 0:

function copyAtPos (dest, vect, i):
    for i from 0 -> vect.length-1 do
        dest[pos+i] = vect[i]

Если вы начнете писать формулу больших сверток, она станет обязательной.

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
3

Почему не 2 или 3 или 20? Это не похоже на то, что массивы на 1 основе проще или проще понять тогда массивы с нулевым основанием. Чтобы переключиться на массивы на основе 1, каждому программисту придется переучиваться, как работать с массивами.

Кроме того, когда вы имеете дело с смещениями в существующие массивы, это также имеет смысл. Если вы прочитали 115 байтов из массива, вы знаете, что следующий фрагмент начинается с 115. И так далее следующий байт всегда равен размеру байта, который вы прочитали. С 1-м основанием вам нужно будет добавлять все все время.

И иногда вам приходится иметь дело с кусками данных в массивах, даже на языке без «истинной» арифметики указателей. В java вы можете иметь данные в картографических файлах памяти или буферах. В этом случае вы знаете, что блок i имеет размер * i. С индексом 1 он будет находиться в блоке * i + 1.

При индексировании на основе 1, много методов потребует + 1с по всему месту.

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
3

Используя массивы на основе 1, преобразуйте одномерный массив в многомерный массив:

int w = 5, h = 5, d = 5;

int[] a1 = new int[w * h * d], new a2 = int[w,h,d];

for (int z = 1; z <= d; z++)

  for (int y = 1; y <= h; y++)

    for (int x = 1; x <= w; x++)

      a1[x + (y - 1) * w + (z - 1) * h] = a2[x,y,z];

Обратите внимание, что ваши y и z индексы основаны на 0 (y - 1, z - 1), даже если ваш массив основан на 1. В некоторых случаях вы не можете избежать индексов на основе 0. Для согласованности почему бы не всегда использовать индексы на основе 0?

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
3

Почему вы хотите, чтобы массивы начинались с одного?

Когда вы говорите a[x][y], компилятор переводит это в: a+(x*num_cols+y). Если массивы начинаются с единицы, это станет a+(x*num_cols+y-1). Это будет дополнительная арифметическая операция каждый раз , к которой вы хотите получить доступ к элементу массива. Почему вы хотите замедлить программы?

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
2

Я собираюсь выйти на конечность здесь и предложить нечто иное, чем целочисленный массив с ключом.

Я думаю, что ваш коллега пытается создать сопоставление «одного набора» в физическом мире, в котором мы всегда начинаем рассчитывать на 1. Я могу понять это, когда вы не делаете ничего необычного, легко понять код, когда вы сопоставлены с 1 по 1 между программным обеспечением и физическим миром.

Мое предложение

Не используйте массивы на основе целых чисел для того, что вы храните, но используйте другой тип словаря или пару значений ключа. Эти карты лучше подходят для реальной жизни, поскольку вы не связаны никаким целым числом. Это имеет свое место, и я бы рекомендовал использовать его как можно больше из-за преимуществ отображения концепций 1 - 1 между программным обеспечением и физическим миром.

то есть. kvp['Name Server'] = "ns1.example.com"; (Это всего лишь один из миллиона возможных примеров).

Discaimer

Это наиболее определенно не работает, когда вы работаете с концепциями, основанными на математике, в основном потому, что математика ближе к фактической реализации компьютера. Использование наборов kvp ничего не поможет, но на самом деле все испортит и сделает его более проблематичным. Я не продумал все угловые случаи, когда что-то может работать лучше как kvp или как массив.

Идея конца состоит в том, чтобы использовать массивы с нулевым основанием или пары ключевых значений, где это имеет смысл, помните, что когда у вас есть только молоток, каждая проблема начинает выглядеть как гвоздь ...

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
2

Лично один аргумент заключается в том, чтобы видеть индексы массивов как смещения. Это имеет смысл.

Можно сказать, что его первый элемент, но смещение первого элемента относительно начала массива равно нулю. Таким образом, получение начала массива и добавление нуля приведет к первому элементу.

Поэтому при вычислении его проще добавить нуль, чтобы найти первый элемент, чем добавить один, а затем удалить его.

Я думаю, что любой, кто делал что-то более низкоуровневое, всегда считал базовый нулевой путь. И люди, которые начинают или используют на более высоком уровне часто не-алгоритмическое программирование, могут пожелать создать базовую систему. Или, может быть, мы просто предвзяты прошлым опытом.

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
2

Только две (очень) серьезные причины использования индексов на основе 0 вместо индексов на основе 1 кажутся , чтобы избежать перевоспитания большого количества программистов и для обратной совместимости .

Я не видел никаких других серьезных аргументов против 1-х индексов во всех полученных вами ответах.

Фактически, индексы естественно 1-based , и вот почему.

Во-первых, мы должны спросить: откуда взялись массивы? Имеют ли они реальные эквиваленты? Ответ да - это то, как мы моделируем векторы и матрицу в информатике. Тем не менее, векторы и матрица представляют собой концепции математических понятий, которые использовали индексы на основе 1 до компьютерной эры (и которые по-прежнему в основном используют индексы на основе 1 в настоящее время).

В реальном мире индексы являются 1-основами.

Как сказал Томас, языки, которые использовали индексы 0-оснований, фактически используют смещения , а не индексы. И разработчики, которые используют эти языки, думают о смещениях , а не о показателях. Это не было бы проблемой, если бы было четко указано, но это не так. Многие разработчики, использующие смещения, все еще говорят об индексах. И многие разработчики, использующие индексы, до сих пор не знают, что C, C ++, C #, ... используют смещения.

Это проблема формулировки .

(Примечание о бумаге Diskstra - В нем сказано точно, что я сказал выше : математик использует индексы на основе 1 . Но Diskstra считает, что математики не должны использовать их, потому что некоторое выражение тогда будет уродливым (например: 1 <= n <= 0). Ну, не уверен, что он прав на этом - делая такой сдвиг парадигмы, чтобы избежать этих исключительных пустые последовательности кажутся много неприятностей для небольшого результата ...)

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
2

Вы когда-нибудь раздражались «20-м веком», фактически ссылаясь на 1900-е годы? Ну, это хорошая аналогия для утомительных вещей, с которыми вы работаете все время при использовании массивов на основе 1.

Рассмотрим общую задачу массива, такую ​​как метод чтения .net IO.stream:

int Read(byte[] buffer, int offset, int length)

Вот что я предлагаю вам сделать, чтобы убедить себя, что массивы на основе 0 лучше:

В каждом стиле индексирования напишите BufferedStream класс, который поддерживает чтение. Вы можете изменить определение функции Read (например, использовать нижнюю границу вместо смещения) для массивов на основе 1. Не нужно ничего фантазии, просто сделайте это простым.

Теперь, какая из этих реализаций проще? У кого есть +1 и -1 смещения, посыпанные здесь и там? Это то, о чем я думал. На самом деле я бы сказал, что единственными случаями, когда стиль индексирования не имеет значения, является то, что вы должны использовать то, что не было массивом, например Set.

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
2

Это из-за того, как строятся массивы. Это не имеет большого значения для них, чтобы начать с одного. Массив - это базовый адрес в памяти, размер и индекс. Для доступа к n-му элементу это:

base + n * element_size

Итак, 0, очевидно, является первым смещением.

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
1

Существует несколько различных способов реализации этого:

  • 0-массивные индексы массива
  • Индексы массивов на основе 1
  • либо массивы на основе 0, либо 1 (например, VB 6.0 ... это действительно ужасно)

В конечном счете, я не думаю, что имеет значение, использует ли язык 0 или 1 массивы. Но я считаю, что лучший выбор - использовать массивы на основе 0, по той простой причине, что большинство программистов используются для этого соглашения, и оно согласуется с подавляющим большинством уже написанного кода.

Единственный способ, которым вы действительно ошибаетесь, - быть непоследовательным, как Visual Basic. База кода, которую я в настоящее время поддерживаю, разделяется между 0 и 1 массивами; и чрезвычайно сложно выяснить, что есть. Это приводит к раздражающе сложному циклу:

dim i as integer, lb as integer, ub as integer
lb = LBound(array)
ub = UBound(array)
for i = lb to ub
       '...
next
ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
1

Zero является естественным, когда речь идет о местоположении элемента в линейной коллекции.

Подумайте о полке, полной книг - первая книга находится заподлицо с боковой стенкой полки - это нулевое местоположение.

Итак, я думаю, это зависит от того, считаете ли вы индексы массива средством поиска вещей или ссылкой на вещи.

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
1

Я предпочитаю индекс на основе 0, так как поскольку modulo (и оператор AND при использовании для modulo) всегда возвращает 0 для некоторых значений.

Я часто использую такие массивы, как это:

int blah = array[i & 0xff];

Я часто неправильно воспринимаю этот код при использовании индексов на основе 1.

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
1

Трудно защищать 0-базу без программирования большого количества массива на основе массива, такого как поиск строк и различные алгоритмы сортировки /слияния, или имитация многомерных массивов в одномерном массиве. Fortran - 1, и вам нужно много кофе, чтобы получить такой код, сделанный правильно.

Но это выходит за рамки этого. Это очень полезная ментальная привычка уметь мыслить о чем-то, а не о показателях его элементов. Например, при использовании пиксельной графики гораздо яснее думать о координатах как о падении между пикселями, а не о них. Таким образом, прямоугольник 3x3 содержит 9 пикселей, а не 16.

Немного более надуманный пример - это идея взглянуть вперед в разборе или на печать итогов в таблице. Подход «здравого смысла» говорит: 1) получить следующий символ, токен или таблицу, и 2) решить, что с ним делать. Подглядывающий подход говорит: 1) предполагайте, что вы можете это увидеть, и решите, хотите ли вы его, и 2) если вы этого хотите, «примите» его (что позволяет вам видеть следующий). Тогда, если вы выписываете псевдокод, это намного проще.

Еще один пример - использование «goto» на языках, на которых у вас нет выбора, например пакетных файлов MS-DOS. Подход «здравого смысла» заключается в прикреплении меток к блокам кода и их маркировке как таковых. Часто лучше использовать ярлыки на концах блоков кода с целью пропустить их. Это делает его «структурированным» и намного проще изменять.

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
1

Это просто так и было на протяжении многих лет. Чтобы изменить его или даже обсудить его, так же бессмысленно изменить или обсудить изменение светофоров. Давайте сделаем blue = stop, red = go.

Посмотрите на изменения, внесенные с течением времени в Numericical Recipes для C ++. Они использовали макросы для подделки индексации на основе 1, но в выпуске 2001 года отказались и присоединились к стаду. Там могут быть материалы для ознакомления по причинам, стоящим за этим на их сайте www.nr.com

BTW, также раздражает варианты выделения диапазона из массива. Пример: python против IDL; a [100: 200] против [100: 199], чтобы получить 100 элементов. Просто нужно изучить причуды каждого языка. Чтобы изменить язык, который делает это одним из способов совпадения с другим, это вызовет такое ругательство и скрежет зубов, а не решит какую-либо реальную проблему.

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
1

Я предпочитаю массивы на основе 0, потому что, как упоминалось другими, он упрощает математику. Например, если у нас есть 1-мерный массив из 100 элементов, эмулирующих сетку 10x10, то каков индекс массива i элемента в строке r, col c:

0: i = 10 * r + c
1: i = 10 * (r - 1) + c

И, учитывая индекс i, возврат к строке и столбцу:

0: c = i% 10
         r = пол (i /10)
1: c = (i - 1)% 10 + 1
         r = ceil (i /10)

Учитывая, что приведенная выше математика явно более сложна при использовании массивов на основе 1, логично выбрать в качестве стандарта массивы на основе 0.

Однако, я думаю, что кто-то может утверждать, что моя логика ошибочна, потому что я предполагаю, что будет причина представлять 2D-данные в 1D-массиве. Я столкнулся с рядом таких ситуаций в C /C ++, но должен признать, что выполнение таких вычислений зависит от языка. Если массивы действительно выполняли всю индексную математику для клиента, все время, то компилятор мог просто преобразовать ваши обращения к массиву на основе M к 0-основанию во время компиляции и скрыть все эти детали реализации от пользователя. Фактически, любая константа времени компиляции может использоваться для выполнения одного и того же набора операций, хотя такие конструкции, вероятно, просто приведут к непостижимому коду.

Возможно, лучшим аргументом было бы то, что минимизация числа операций индекса массива на языке с массивами на основе 1 потребует, чтобы целочисленное деление выполнялось с использованием функции потолка. Однако с математической точки зрения целочисленное деление должно возвращать d остаток r, где d и r оба положительные. Поэтому для упрощения математики следует использовать массивы на основе 0.

Например, если вы создаете таблицу поиска с N элементами, ближайший индекс до текущего значения в массиве для значения x будет (приблизительно, игнорируя значения, где результат представляет собой целое число до округления):

0 на основе пола: пол ((N - 1) * x /xRange)
1 на основе пола: пол ((N - 1) * x /xRange) + 1
1 - с потолком: ceil ((N - 1) * x /xRange)

Обратите внимание, что если используется стандартное соглашение округления, массивы на основе 1 требуют дополнительной операции, что нежелательно. Этот вид математики не может быть скрыт компилятором, поскольку он требует знания более низкого уровня о том, что происходит за кулисами.

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
1

Я уверен, что программист был просто раздражен встречной интуитивностью массива, основанного на 0, в повседневном мышлении и аргументировал себя более интуитивным средством описания массивов. Мне показалось, что, как люди, мы потратили столько времени, чтобы придумать «классы», чтобы мы могли описать вещи более человечным образом в нашем коде, но затем, глядя на 0 против 1 массива, мы, похоже, логика одного.

Что касается компьютера, и математически 0, вероятно, будет лучше, но я чувствую, что здесь пропущена точка. Если бы мы хотели описать вещи более человечным образом (например, классы), почему бы нам не хотеть того же для других частей языка? Разве это не так логично или справедливо (или принимать более высокий приоритет в этом отношении ...), чтобы сделать язык более понятным и доступным для людей, и, следовательно, в более широком смысле, менее подвержен сценариям, которые, как правило, создают логические ошибки и более склонны для ускорения производства полезного создания. Пример PHP:

array(1 => 'January', 'February', 'March');

дает массив по 1 на наш запрос.

Почему not имеют норму:

array('January', 'February', 'March');

И исключение:

array(0 => 'Value for scenario where 0 *has* to be used as the key',
      'value2', 'value3');

В случае, скажем, PHP, моя ставка составляет 80% времени, когда массив, основанный на 1, является синтаксисом по умолчанию, уменьшит логические ошибки в реальных случаях использования или, по крайней мере, не приведет к увеличению в среднем, намного проще на кодере быстрее производить полезный код. Помните, я предполагаю, что по-прежнему будет опция array (0 => 'value') для того, когда это необходимо, но также предполагая, что в большинстве случаев практично иметь что-то ближе к описанию реального мира.

Это действительно звучит слишком далеко от запроса, если смотреть на него с этой точки зрения. При приближении к интерфейсу, будь то ОС или язык для программиста, чем ближе к человеческому мышлению и привычкам мы его разрабатываем, тем счастливее в большинстве случаев мы будем и тем меньше недоразумений между человеком и компьютером (человеческая логика - ошибки), и более быстрое производство и т. д. мы будем иметь. Если 80% времени в реальном мире я описываю вещи с 1 при составлении списков или подсчета, то компьютер должен в идеале интерпретировать мой смысл так, как он понимает с минимальной информацией или изменяет мой обычный способ описания чего-либо, насколько это возможно. Короче говоря, чем ближе мы можем моделировать реальный мир, тем лучше качество абстракции. Так что он хочет отнюдь не глупо, поскольку это конечная цель и будет свидетельством необходимости в большей абстракции. В конечном итоге компьютер может рассматривать его как специальное использование массива, основанного на 0. Мне было все равно, как компьютер интерпретирует его, пока это более простой и интуитивно понятный способ описать то, что я хочу, с меньшими ошибками с течением времени.

Итак, это мои два цента. Я серьезно сомневаюсь, что он говорил или что толкует, что он имел в виду. То, что он, вероятно, имел в виду, было: «Мне не нравится иметь менее интуитивный способ сказать компьютеру то, что я хочу». :) Разве мы не все? лол.

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54
1

Это возможно, если вы берете на себя заботу при написании своего «собственного» кода. Вы можете предположить, что ваш индекс начинается с n для всех n> = 0 и программы соответственно.

Что касается стандарта, Borealid имеет большой аргумент.

ответил Benyamin Limanto 21 J0000006Europe/Moscow 2016, 07:39:54

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132