Почему компьютеры считают с нуля?

10070
bwDraco

Компьютеры традиционно подсчитывают числовые значения, начиная с нуля. Например, массивы в языках программирования на основе C начинаются с нуля индекса.

Какие исторические причины для этого существуют, и какие практические преимущества имеет счет от нуля по сравнению с счетом от одного?

Примечание. Этот вопрос требует хорошо объясненных технических ответов, а не просто мнений, и предназначен для охвата компьютеров в целом, а не только программирования. Этот вопрос расширяет вопрос программистов "Почему структуры / массивы начинаются с нуля?" ,

55
[Мнение Djkstra] (http://www.cs.utexas.edu/users/EWD/ewd08xx/EWD831.PDF) Bakuriu 11 лет назад 16
Потому что компьютеры используют основную числовую систему 2. Ramhound 11 лет назад 3
Было более чем несколько примеров компьютерных языков, которые использовали массивы с 1 источником. Daniel R Hicks 11 лет назад 9
(И компьютеры, которые считают в десятичном, восьмеричном, на 3 с, на 100 с, и др.) Daniel R Hicks 11 лет назад 1
Я надеюсь, что DL не спросит насчет ошибки с плавающей точкой и округления. Psycogeek 11 лет назад 1
Почему люди не считают от 0? Untitled 11 лет назад 23
@ Без названия Определенно согласен. Первое натуральное число - ноль, потому что в действительности вполне допустимо иметь ноль вещей. И операции упрощены. Alba Mendez 11 лет назад 0
Вау, вау, никто не считает с нуля, мы * индекс * с нуля. Никто не говорит "нулевой" элемент. Мы говорим «первый» элемент в * index * 0. Думайте об индексе как о смещении элемента от первой позиции. Итак, первый элемент находится на первой позиции, поэтому он вообще не смещен, поэтому его индекс равен 0. Второй элемент, как один элемент перед ним, поэтому он смещен на 1 элемент и имеет индекс 1 mowwwalker 11 лет назад 46
По той же причине, что годы 20-го века все в форме 19xx. В 1-м веке столбцы «тысячи» и «сотни» были равны нулю. В 1-е десятилетие так же были «десятки». Хотя 1-й год можно назвать «Год 1», он _starts_ в _position_ ноль. Stewart 11 лет назад 4
@ Ramhound Нет, это не так. Индексирование на основе нуля совершенно не связано с использованием двоичного кода. Peter Olson 11 лет назад 14
До компьютеров была математика. В математике все начинается с 0. Мой учитель абстрактной алгебры сказал бы, что часы должны иметь 0 вместо 12, так как это интерфейс мода 12. avgbody 11 лет назад 4
@PeterOlson - я не согласен с вами. Ramhound 11 лет назад 0
@ Без названия: Мы * считаем * от 0. Потому что если у вас есть один элемент, мы получаем 1, поэтому, прежде чем у нас был один элемент, у нас было 0. Der Hochstapler 11 лет назад 2
@ Walkerneo Точно. Оливер Зальцбург: Перед первым элементом было нечего считать. Ярослав Рахматуллин 11 лет назад 0
Люди считают с нуля. Сколько пальцев я держу? (Закрытый кулак). Нуль. Чтобы считать, вы начинаете с нуля. Затем, если какие-либо элементы или события, представляющие интерес, происходят, вы увеличиваете один раз для каждого из них. Итоговое значение - это количество. Подсчет должен включать в себя возможность того, что ничто не считается, иначе оно нарушено. Kaz 11 лет назад 0
Аксиомы Пеано просто утверждают, что множество натуральных чисел имеет элемент, который он назвал «один», так что не существует ни одного натурального числа n, такого, что преемник n равен единице. Вы можете выбрать, какой символ будет представлять «один» элемент по желанию. При желании это может быть -10 или буква «а». emory 11 лет назад 0
Вот еще одна глупость, любезность музыкантов (пьяная партия). Шкала с семью нотами называется октавой! Конечно, давайте посчитаем С дважды, почему бы и нет. Хорошо, у нас пока семь и восемь. Тогда интервалы основаны на одном, поэтому у нас есть девять правил инвертирования: инвертируйте третий, и вы получите (9 - 3) шестое. Ура! Три числа, чтобы иметь дело с чем-то более простым. Под нулевыми интервалами у нас есть септавы (или гептавы). И интервал инвертируется путем вычитания из 7. Семь нот, септав, правило семи. Kaz 11 лет назад 0
Мне напоминают, что IBM 650, относительно популярный ранний компьютер, использовал [bi-quinary] (http://en.wikipedia.org/wiki/Bi-quinary_coded_decimal) хранилище данных. Думай счеты. Daniel R Hicks 11 лет назад 0
@DragonLord Эта статья может быть полезна http://www.howtogeek.com/149225/why-do-computers-count-from-zero/ Simon 11 лет назад 0
@Simon: Wow я знаменит `: P` bwDraco 11 лет назад 0
@DragonLord Очевидно, вопрос стоит написать :) Simon 11 лет назад 0

17 ответов на вопрос

87
Matteo

Подсчет массивов от 0 упрощает вычисление адреса памяти каждого элемента.

Если массив хранится в данной позиции в памяти (это называется адресом), позиция каждого элемента может быть вычислена как

element(n) = address + n * size_of_the_element 

Если вы считаете первый элемент первым, вычисление становится

element(n) = address + (n-1) * size_of_the_element 

Не сильно отличается, но добавляет ненужное вычитание для каждого доступа.

редактировать

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

  • Дейкстра опубликовал статью «Почему нумерация должна начинаться с нуля» ( pdf ), где он объясняет, почему начинать с 0 - лучший выбор. Начиная с нуля, можно лучше представить диапазоны.

+1 за правильный ответ. Обратите внимание, что индексирование на основе 0 является * (очень распространенным) * соглашением используемого языка; это не универсально. Например, [Lua использует индексирование на основе 1] (http://stackoverflow.com/questions/2785704/why-do-lua-arraystables-start-at-1-instead-of-0). «Ненужное вычитание» могло быть причиной индексации на основе 0 в старые времена, но сейчас большинство языков используют ее просто потому, что это то, к чему все уже привыкли * (во многом благодаря C) *, и нет веских причин для этого изменить это соглашение. BlueRaja - Danny Pflughoeft 11 лет назад 8
Это правильный ответ. Yuck 11 лет назад 0
Это не имеет никакого смысла. Положение каждого элемента всегда может быть вычислено как `address + n * size_of_element`, если« address »- это адрес нулевого элемента. Это прекрасно работает независимо от того, существует ли нулевой элемент как элемент массива или нет. Вопрос в том, почему существует нулевой элемент, а не в том, почему мы храним адреса в качестве адреса (возможно, условного) нулевого элемента. (На что это отвечает.) David Schwartz 11 лет назад 2
@DavidSchwartz Конечно, но в этом случае нулевой элемент не будет адресуемым. Если ваш массив начинается с 1, вы никогда не будете использовать нулевой элемент. Matteo 11 лет назад 0
@DavidSchwartz Ответ не ** неправильный **. Когда появились первые языки, выбрасывающие память, было даже хуже, чем делать дополнительные вычисления при каждом доступе. Я не утверждаю, что это единственный способ вычислить адрес, но я утверждаю, что именно по этой причине адресация начинается с 0. Matteo 11 лет назад 0
@Matteo: Какое отношение имеет выбрасывание памяти? Сохранение адреса массива в качестве адреса нулевого элемента не приведет к потере памяти, если нулевой элемент не существует. Вам не придется выделять место для этого. Ответ неверный. David Schwartz 11 лет назад 1
@DavidSchwartz Давайте возьмем * старый * язык как C. Если выделить память, вы получите адрес, с которого она начинается. Если компилятор видит что-то вроде `v [n]`, он должен вычислить адрес выражения. Если индексы начинаются с 0, вычисление имеет размер v + x *. Если в 1 вычисление v + (x-1) * размер. Например, v [1] будет соответствовать размеру v + (1-1) *, то есть v. Matteo 11 лет назад 3
давайте [продолжим обсуждение в чате] (http://chat.stackexchange.com/rooms/8208/discussion-between-david-schwartz-and-matteo) David Schwartz 11 лет назад 0
@David: В C * (языке, который действительно популяризировал индексирование на основе 0) *, массивы и указатели в значительной степени взаимозаменяемы, поэтому важно по ряду причин, что `* array` фактически ссылается на первый элемент. Один пример: если у нас есть `массив`, указывающий на область памяти * перед * первым элементом, приведение к массиву другого типа будет проблематичным, например. позиция второго байта в массиве int будет зависеть от размера слова; на 32-битной машине это было бы в `((char *) intArray + 5)` !! BlueRaja - Danny Pflughoeft 11 лет назад 4
Правильно, поэтому ответ таков, что нулем будет первый элемент массива, что означает, что адрес массива может быть адресом его первого элемента, и вы все равно можете вычислить адреса элементов в массиве как «base + index * size` , Это означает, что вы можете обращаться с обычными объектными указателями и одноэлементными массивами одинаково. Это то, что позволяет C-массивам и указателям взаимодействовать так гладко и легко. David Schwartz 11 лет назад 0
Нет, это не проблема того, имеет ли массив нулевой элемент. Потому что, вы видите, есть также масштабирование. Если у меня есть массив из 8-байтовых объектов, и я наложил его на байтовый массив, что такое байтовый индекс объекта [42]? Почему это просто: 42 * 8. Проблема с 1 на основе состоит в том, что это смещение 1 составляет 1 байт, когда я смотрю на массив байтов, и 8 байт, когда я смотрю на наложенный массив 8-байтовых блоков. Kaz 11 лет назад 3
37
Dougvj

Хотя приведенные ниже принципы применимы и к десятичной, и к любой другой базе, отсчет от 0 в компьютерах можно легко понять из двоичной системы с фиксированными цифрами для представления чисел, используемых в компьютерах. Если у вас есть 8 битов, то есть 256 возможных комбинаций 1 и 0, которые могут быть выражены. Вы можете использовать эти 8-битные числа для выражения чисел 1-256, но при этом не будет 0, что полезно в математике как само по себе число, поэтому они используются для выражения чисел 0-255.

Это уже устанавливает прецедент естественного порядка, начиная с 0 (все 0 в двоичном представлении) до 255 (все 1 в 8-битном числе). Рассматривая систему представления чисел, начинать с 0 имеет смысл, потому что 0 - это «первое» число в системе, поэтому 1 - это «второе» число и так далее.

Дополнительная причина, по которой начинать с 0 в компьютерах так удобно, связана с концепцией смещений. Смещение - это число, представляющее расстояние от места в памяти, на жестком диске или на любом другом «адресуемом» носителе. В компьютерах практически все данные хранятся линейно, что означает, что существует порядок данных: первый байт, второй байт и т. Д. Удобно выражать местоположение «областей» данных через смещение. Какой первый байт в блоке данных? Он находится со смещением «0», что означает, что он находится в 0 байтах после первого байта в блоке данных. Несмотря на то, что «1» может обозначать первый байт, это создает сложности при представлении данных по нескольким причинам:

  • Исключая использование 0 для адресации данных, вы сокращаете число вещей, к которым вы можете обращаться с помощью 8-битного числа, на единицу.
  • Чтобы вычислить смещение, которое необходимо на аппаратном уровне доступа к данным, в какой-то момент вы должны вычесть одно из нумерации, что представляет сложность.
  • Указатели на блок данных всегда указывают на первый блок, поэтому арифметика проста, когда вы начинаете с 0. (т.е. 1-й байт в первом блоке первого кластера данных равен 0 + 0 + 0, когда вы начинаете с 0, это 1 + 1 + 1 - 1 -1, когда вы начинаете с 1.) Арифметика для этого, когда вы начинаете с 1 с вложенными структурами данных, как этот пример, может сбивать с толку.
Я могу видеть, начиная с 0, когда ничего нет, я хотел бы, чтобы кто-то мог объяснить, почему 1-й диск равен 0, а сейчас это 1 диск. Обернитесь и назовите 1-й раздел 1, когда он начинается с нуля (0). Я мог понять, почему первый раздаемый IP-адрес был бы равен 0, поскольку это могло бы идентифицировать Сервер / Мастер, а остальные могли быть пронумерованы. Так почему же он начинается с 1? В шестнадцатеричном редакторе 1-й блок равен 0, но там почти всегда есть 1 что-то, но в текстовом редакторе счетчик символов равен 0, когда его там нет. Я думаю, что люди вовлечены, особенно когда они пытаются разделить на 0 * + сбой + * Psycogeek 11 лет назад 0
Не имеет ничего общего с двоичным представлением. Как двоичные, так и десятичные числа начинаются с 0. Matteo 11 лет назад 30
Если вы начнете считать с 0, вы не уменьшите количество адресов, которые вы могли бы (теоретически) перейти от 1 до 257. Matteo 11 лет назад 2
хороший ответ Проведя собственное исследование, я нашел цитаты, которые больше поддерживают вторую часть ответа. В терминах непрофессионала старые языки имели концепцию нуля, потому что, как сказал @Dougvj, данные хранились в лениарных блоках массивов. Таким образом, смещение входит в картину. Для совпадения с нумерацией массива они начали индексирование с 0. Надеюсь, это помогает adithya 11 лет назад 0
@Matteo ни в одном байте вы не могли OrangeDog 11 лет назад 6
@OrangeDog Конечно, я мог: с одним байтом я получаю 256 значений, как я ** интерпретирую ** их (0-255, 1-256, 300-555) не имеет значения. Matteo 11 лет назад 0
@Matteo, но вы сказали 1-257, что составляет 257 значений. OrangeDog 11 лет назад 1
@OrangeDog Упс извините ... Matteo 11 лет назад 1
«255 (все 1 в 8-битном числе)» Вы думаете, что дополняете двойки. В [своем 'дополнении] (http://en.wikipedia.org/wiki/One%27s_complement) (который когда-то был достаточно распространенным, особенно во временных рамках, к которому относится этот вопрос) все двоичные числа всех единиц представляли `-0 `, а не` 2 ^ n - 1` для `n` битов. a CVn 11 лет назад 1
@Matteo вы правы, десятичный и двоичный оба начинаются с 0. Мой акцент больше делается на ограничении двоичного представления в самом физическом компьютере, где 0 - первое число в конечном множестве, и это намного важнее, чем в математическом десятичном, где есть нет конечного набора чисел. Конечно, комплимент двойки вводит отрицательные числа, которые полезны в математике, но также в качестве смещений, когда первый байт перед блоком задан -1. По необходимости первый байт в блоке все еще равен 0. Dougvj 11 лет назад 0
@Dougvj Нулевой отсчет абсолютно не имеет ничего общего с двоичным. Смысл того, что вы делаете, заключается в использовании каждого числа в представлении с фиксированной цифрой, что является проблемой независимо от того, используете ли вы базу 2, базу 10 или базу 23517. Peter Olson 11 лет назад 8
-1 Это не имеет ничего общего с двоичным представлением. BlueRaja - Danny Pflughoeft 11 лет назад 2
@ Питер Олсен. Ты прав. Я не собирался подразумевать, что это было исключительным следствием использования базы 2. Я поясню это. Dougvj 11 лет назад 0
@BlueRaja Я думаю, что разъяснил этот аспект лучше. Dougvj 11 лет назад 0
Я думаю, что вы также должны упомянуть операции по модулю. Matlab имеет индексирование на основе 1, и если вы когда-либо пытались модулировать что-либо в цикле, вам, вероятно, хотелось бы, чтобы оно основывалось на нуле. :) Corporal Touchy 11 лет назад 0
Акцент этого ответа на двоичном коде вводит в заблуждение. Это не смягчается упоминанием о том, что «принципы… применимы и к десятичному типу» - это просто красная сельдь, чтобы вообще упомянуть двоичную, и это мешает пониманию. Нет соединения. Konrad Rudolph 11 лет назад 1
@Konrad Rudolph Вы можете быть правы, но ОП запросил объяснение с точки зрения не программирования. Понимание двоичного кода помогает понять, почему компьютеры на архитектурном уровне начинаются с 0. Я не знаю, как более четко это сделать, не обращаясь к двоичному. Dougvj 11 лет назад 0
@Dougvj Хорошо, посмотрите на другие высоко оцененные ответы. Konrad Rudolph 11 лет назад 0
26
Ярослав Рахматуллин

Никогда не думал, что такая возможность для такого философа, как я, появится на Superuser. В основе лежит фундаментальное заблуждение, потому что нефилософы склонны пропускать мелкие детали. Вкратце: компьютеры не отсчитывают от нуля, но наименование позиций начинается с нуля.

В этом кажущемся несоответствии между компьютерной и человеческой (любой) техникой подсчета нет ничего странного. Давайте разложим вопрос.

Почему компьютеры считают с нуля?

  • Они не считаются с нуля

Компьютеры подсчитывают значения, начиная с нуля. Например, массивы в C.

  • Индекс (индикатор положения, подсчет) начинается с нуля. Количество элементов в массиве, где есть один элемент с индексом ноль один

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

В том же смысле, что и средняя точка шкалы, ноль можно использовать для представления самого края (абсолютного начала) коллекции. Вопрос не имеет смысла, потому что он не согласуется между «значениями подсчета» и «отсчетом с нуля».

Так что да, компьютеры подсчитывают с нуля, но они считаются с одного. Два слова имеют разное значение.

tal·ly [tal-ee]

имя существительное

  1. счет или расплата; запись дебета и кредита, счета в игре или тому подобное.
  2. все, на чем ведется счет или счет ..
  3. количество или группа записанных предметов.

считать [ количество ]

глагол (используется с объектом)

  1. проверять (отдельные единицы или группы коллекции) одну за другой, чтобы определить общее количество; сложить; перечислите: он пересчитал свои билеты и обнаружил, что у него было десять.
  2. считаться; вычислить; вычислить.
  3. перечислить или назвать цифры до: Закройте глаза и сосчитайте до десяти.

(Dictionary.com)


Практические причины адекватно описаны Дугви, мне нечего там добавить. Если бы у нас был профессор CS (60-х годов), чтобы дать исторический отчет ...

На самом деле, откуда вы знаете, где компьютер запускает что-нибудь? Все, что вы знаете, это то, что, когда вы используете это, вы говорите, чтобы начать с нуля. Daniel R Hicks 11 лет назад 0
Я говорю здесь об определениях концепций и логики, а не о том, как компьютеры работают сами по себе. Я немного знаю о том, откуда начинаются компьютеры, потому что я прошел курсы CS. Ярослав Рахматуллин 11 лет назад 0
Чтобы быть полностью педантичным, вы сравниваете глагол с существительным. Я думаю, что «счет» и «счет» действительно являются синонимами, и оба могут использоваться как глагол или существительное. Brian 11 лет назад 1
@ Брайан Справедливое наблюдение, и я намерен показать (педантично), что путаница проистекает из неправильного толкования терминов. На самом деле нет разницы между «1-м элементом» и «элементом в позиции 0». Они оба элемент один. * Первый *, а не "* ноль *". Нет такой вещи, как "отсчет с нуля". Перечисление начинается с * one * по определению, а адресация может быть a-> 1, b-> 2. с-> 3 или 0-> 1, 1-> 2, 2-> 3. Наиболее распространенный пример «отсчета от нуля» можно найти в книгах по математике в средней школе в виде - но индекс - это * index *. Ярослав Рахматуллин 11 лет назад 1
@ ЯрославРахматуллин - Я тоже прошел несколько курсов CS. И разработал компьютеры и схемы LSI и написанные компиляторы и JITC Java. Daniel R Hicks 11 лет назад 0
@DanielRHicks Я не могу похвастаться обширным (или каким-либо другим) практическим опытом, но я придерживаюсь, основываясь на интуиции и моих скудных теоретических знаниях в этой области, что: * Обычный дизайн - индексировать с нуля. И подсчет одного элемента по нулевому индексу должен дать 1, если он разработан в соответствии с определением концепций. * Попытка дискредитировать мой ответ на основании моего опыта или знаний бесполезна, поскольку он не опирается ни на что из этого. Всем спасибо за комментарии. Мне было весело отвечать на этот вопрос и отвечать на комментарии, но я не думаю, что дальнейшее повторение что-нибудь прояснит. Ярослав Рахматуллин 11 лет назад 0
Просто дизайнеры действительно немного побродили, прежде чем остановились на текущей схеме. То, что кажется «очевидным», теперь не было. И, вероятно, могла бы быть выбрана несколько иная схема, которая теперь казалась бы более «очевидной», чем у нас. Daniel R Hicks 11 лет назад 1
[Bi-quinary] (http://en.wikipedia.org/wiki/Bi-quinary_coded_decimal), например. Daniel R Hicks 11 лет назад 0
12
NevilleDNZ

Я думаю, что это уже освещалось " проф. Доктором Эдсгером В. Дейкстра " - научным сотрудником Берроуза в письме от 11 августа 1982 г .: cf EWD831

Под названием: Почему нумерация должна начинаться с нуля . «Есть ли причины отдавать предпочтение одному соглашению другому? Да, есть…»

Также обратите внимание, что Дейкстра был в команде разработчиков ALGOL 68 до 1968 года. Algol68 допускает массивы либо от 0, 1, либо от любого числа, которое программист сочтет подходящим для алгоритма. cf ( «Создание Алгола 68» рассказывает: «Можете ли вы определить треугольные массивы?» кто-то (Тони Хоар?) прервал. «Не только треугольный, но даже эллиптический», ответил Аад и показал, как ».)

В частности, в Algol68, когда массивы (и матрицы) срезаются, они получают индекс @ 1, поэтому наблюдается смещение к массивам [1: ...]. Но «1- ую » нижнюю границу можно переместить, чтобы начать с «0- й » позиции, указав «@ 0», например, вектор x [4: 99 @ 2], матрицу y [4: 99 @ 1,4: 99 @ 0]. Аналогично, по умолчанию / смещение от 1 в циклах do ~ od (если явно не указано " from 0") и от 1 для целочисленного случая i в ~, ~, ~ esac и $ c (~, ~, ~ ) $ выбор статей.

Кажется, что комментарии Дейкстры о мартовском проекте отчета 1968 года ( MR93 ) и его настойчивость спровоцировали то, что, возможно, является войной пламени до начала использования : «есть сочинения, которые привлекательны, хотя и не грамматичны, и есть другие сочинения, которые являются чрезвычайно грамматическими, но отвратительно. Это то, что я не могу объяснить поверхностным людям ". EWD230

Заключительный отчет Алгола 68 (FR) был опубликован 20 декабря 1968 года, когда он был представлен на Мюнхенском совещании, а затем принят Рабочей группой. Впоследствии отчет был утвержден Генеральной Ассамблеей ИФИП ЮНЕСКО для публикации.

Около 23 декабря (?) 1968 года Дейкстра, Дункан, Гарвик, Хоар, Рэнделл, Зигмюллер, Турски, Вуджер и Гарвик подписали «Отчет меньшинства» AB31.1.1.1, стр. 7 (опубликовано в 1970 году).

10
Random832

Дистанционная аналогия, приведенная кем-то другим, дает очень практическую иллюстрацию:

"Как далеко ваш дом от ближайшей заправки?"

"1 миля"

"Вы живете на заправке?"

«Нет, если бы я жил на заправке, это было бы 0 миль»

"Почему ты считаешь с нуля, а не с одного?"

Другим хорошим примером были бы дни рождения - мы не говорим, что кому-то исполнился год, а мы - год спустя.

Мы говорим о високосных годах или президентских выборах в США каждые четыре года, даже если считать одно: 2000, 2001, 2002, 2003, 2004 годы - пять лет. (Между прочим, римляне на некоторое время облажались, и високосные годы были слишком близко друг к другу)

Суть в том, что в реальном мире мы все время «отсчитываем» от нуля - «Сколько позиций после [начала массива] - это элемент, который вы хотите» просто оказывается вопросом, на который вы отвечаете с отсчетом от нуля во многих компьютерных программах. Вы бы не сказали, что первый элемент - одна позиция после старта, не так ли? Это является началом.

Ваша математика относительно выборов выключена на год. Ваш пример содержит 2 года выборов в течение 5 лет; правильной иллюстрацией будет то, что 4 года проходят от одного выбора к другому, то есть 2000 -> 2001 (1 год), 2001 -> 2002, 2002 -> 2003, 2003 -> 2004. Jimmy 11 лет назад 1
@Jimmy Это была моя точка зрения - если бы люди «считали с одного» в том смысле, в каком они хотят компьютеров, они считали бы 2000 как единое целое, а не как ноль. Кстати, именно так на самом деле это делали древние римляне (и действительно описывали бы цикл, подобный «2000, 2004, 2008», как пятилетний цикл). Random832 11 лет назад 1
Пример вашего дня рождения не всегда правдив. Например, [в Южной Корее первый год жизни считается одним вместо нуля] (http://en.wikipedia.org/wiki/East_Asian_age_reckoning). BennyMcBenBen 11 лет назад 2
6
Jack Aidley

Как уже говорили другие компьютеры, не считайте с нуля .

Индекс некоторых языков от 0. Индексирование от 0 имеет два основных преимущества:

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

  2. Вы не получаете странности, когда вы хотите негативы. Сколько лет между 1BC и 1AD? Никто. Потому что, хотя до н.э. фактически отрицательные даты, нулевого года нет. Если бы был 0AD, не было бы здесь никаких проблем. Вы видите ту же проблему повсюду в науке, где люди наивно определили первый элемент в наборе как +1.

Да и вся глупость ждать до 2001 года нового тысячелетия. Это смутило именно тех людей, которые также не «получают» массивы, основанные на нуле, когда они увлекаются программированием. :) Kaz 11 лет назад 0
Кроме того, если «1 миля» означает «прямо здесь», то, поскольку миля составляет 1760 футов, это означает, что «1760 футов» также означает «прямо здесь», верно? Неправильно, «1 фут» означает прямо здесь, ой! В этой основанной на глупости «прямо здесь» один фут, один дюйм, один сантиметр и т. Д. Kaz 11 лет назад 3
@kaz где ноги => ярдов. 1760 ярдов в миле. Brad 10 лет назад 0
3
Kaz

Подсчет естественно начинается с нуля

Вот алгоритм подсчета яблок в корзине:

count := 0  for each apple in basket count := count + 1 

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

Если вы не пользуетесь своей кредитной картой целый месяц, получаете ли вы счет в 1 доллар? Или 1 цент?

Когда вы сбрасываете счетчик пробега на одометре вашего автомобиля, он переходит на 0001 или 0000?

Массивы могут предоставлять несколько представлений одних и тех же данных.

Рассмотрим массив из 32-битных структур d, каждая из которых состоит из 16-битных слов w. Каждое слово состоит из двух 8-битных байтов b. При нулевой индексации наложение выглядит очень удобно:

d: | 0 | 1 | w: | 0 | 1 | 2 | 3 | b: |0|1|2|3|4|5|6|7| 

32-битный объект d[1]по адресу слова, w[2]который легко вычисляется путем умножения индекса на 2, который является отношением размеров 32- и 16-битного объекта. Кроме того, в байтовой адресации это так b[4].

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

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

С одним основанным индексированием это ломает:

d: | 1 | 2 | w: | 1 | 2 | 3 | 4 | b: |1|2|3|4|5|6|7|8| 

Теперь мы не можем просто умножить dиндекс на 2, чтобы получить wиндекс, или на 4, чтобы получить bиндекс. Преобразование между единицами становится неуклюжим. Например, чтобы перейти от d[2]к b[4], мы должны рассчитать ((2 - 1) * 4) + 1 = 5.

Мы должны вычесть это надоедливое смещение 1 в dединицах, затем выполнить масштабирование в естественной системе координат, основанной на нуле, и затем добавить обратно надоедливое 1 в bединицах. Обратите внимание, что это не то же самое 1! Мы вычитаем ширину одного двойного слова, но затем добавляем ширину в один байт .

Преобразование между различными представлениями данных становится чем-то вроде преобразования Цельсия-Фаренгейта.

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

Минимизация цифр

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

Это важно в компьютерах, потому что количество цифр в двоичном коде переводится в аппаратные адресные строки. Например, чип ПЗУ с 256 словами в нем может быть адресован от 0 до 255, что требует 8 битов: от 00000000 до 11111111. Если он адресован от 1 до 256, то необходимы девять битов. Мы должны расточительно добавить еще одну трассировку адресов к плате или интегральной схеме. Так что на практике может случиться так, что 0 будет просто называться1 на уровне программного API для доступа к этому чипу. Запрос слова 1 фактически поместил бы 00000000 на 8-битную адресную шину. В противном случае запрос на 1 будет преобразован в адрес 00000001, как и ожидалось, но запрос на 256 будет сопоставлен с неиспользуемым в противном случае 8-битным адресом 00000000, а не с 9-битным адресом 100000000. Оба этих кладбищ-кусочка действительно являются решениями в поиск проблемы, и полностью исключаются путем последовательного использования от 0 до 255 на оборудовании, в программном обеспечении и во всех пользовательских интерфейсах и документации.

Единичные смещения в корне глупы

Рассмотрим, например, западную теорию музыки. У нас есть диатонические весы с семью нотами, но мы называем пространство, которое они покрывают октавой ! Затем инверсия интервалов следует правилу девяти : например, инверсия третьего является шестым (вычтите три из девяти). Таким образом, три разных числа используются для чего-то такого простого: семь (ноты в шкале), восемь (октава) и девять (от вычитания до инвертирования).

Если бы семь нот составляли септав или гептав, а интервалы были равны нулю, то мы вычли бы из семи до инвертирования. Все основано на семи.

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

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

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

Системы на основе одного путают одних и тех же людей, которые не могут обрабатывать массивы с нулями

Когда наступил 2000 год, многие были озадачены тем, что новое тысячелетие не началось. Те, кто указывал на то, что это не начнется до 2001 года, были расценены как партийные пижоны и паутины. В конце концов, вам 20, когда вам исполняется 20, верно? Не тогда, когда вам исполнится 21 год. Если вы думали, что тысячелетие началось 1 января 2000 года, то вы не имеете права жаловаться на массивы с нулями на любом языке программирования. Они работают так, как вам нравится. (Но, да, сторонниками смещений и массивов по принципу «один на один» являются dweebs и party-poopers. Столетия должны начаться в XX00 годах, а тысячелетия - в X000 лет.)

Календари тупые, но по крайней мере время суток начинается с нуля

Каждая новая минута на ваших часах начинается с: 00 секунд. Каждый новый час начинается с 00:00 минут и секунд. И, по крайней мере на 24-часовых часах, день наступает, когда наступает полночь, и 11:59:59 увеличивается до 00:00:00.

Таким образом, если вы хотите вычислить секунды с полуночи для времени, подобного 13:53:04, вам просто нужно оценить 13 * 3600 + 53 * 60 + 4. Нет безвкусных 1дополнений или вычитаний.

Закрывающая напыщенная речь о MIDI

Хорошо, что это с музыкантами, даже предположительно техническими?

MIDI! Он использует нумерацию с нуля для программ и каналов при фактическом представлении сообщений в проводном режиме, но устройство Gear отображает его как 1 на основе! Например, программы от 0 до 127 на большинстве передач называются от 1 до 128, но некоторые вызывают их от 0 до 127 или даже предоставляют пользователю выбор.

Программы с 71 по 80 считаются «банком» из десяти. Так сказано прямо на моей педали MIDI, например. Футсвитчи помечены цифрами от 1 до 10, и, если я нахожусь в седьмом банке, они выбирают программы с 71 по 80. Однако некоторые устройства или компьютерные программы отображают номера программ с 1 по 128 от 0 до 127 или даже дают пользователю выбор! Что хуже: системы на основе одного или хаос, созданный с использованием как одного, так и нулевого уровня, основанного одновременно?

Номера каналов MIDI называются от 1 до 16, но представлены двоичными числами от 0 до 15. Как будто вне зависимости от представления на основе одного, некоторые устройства используют дисковый переключатель для настройки номера канала, и часто эти переключатели просто используют двоичный код на основе нуля. Таким образом, если вы хотите канал 3, вы должны переключить его на 0010 (двоичный 2).

1
unknownprotocol

Если я правильно помню из моего класса «Концепции языка программирования» ... языки с 0 индексами и другие с 1 индексом были связаны с историческими причинами. Алгол-68, прародитель языков программирования был на самом деле 1-индексирован, а также Фортран и некоторые другие «деловые» языки, такие как COBOL. Однако в некоторых из этих языков вы могли бы явно указать, каким будет ваш начальный индекс. Там очень интересная таблица это здесь .

В основном в « Ye Olde Days » математики, ученые и другие «академики» обычно использовали 0-индексированные языки, в то время как пользователи таких языков, как COBOL, не нашли смысла начинать считать с 0, поэтому в этих языках было больше смысла начать с 1 (это казалось менее запутанным).

Теперь, если ваш вопрос касается того, почему компьютер ( не язык ) естественным образом начинает считать с нуля ... ну, я думаю, что в действительности двоичный код присущ: ex: 0000= zero 0001= one ... и так далее, и так далее. далее ...

Не имеет ничего общего с двоичным представлением. Как двоичные, так и десятичные числа начинаются с 0 (как показано в вашем примере). Matteo 11 лет назад 4
Ну, это как-то связано с бинарным. С четырьмя битами, от 0000 до 1111, вы можете обратиться к банку памяти из 16 слов. Если вы делаете это по одному, тогда вам нужно пять адресных строк для представления от 0001 до 10000. Или же вы делаете то, что, например, MIDI делает с номерами каналов: 0000 используется внутри, но пользовательские интерфейсы показывают 1! Если бы аппаратное обеспечение основывалось на десятичной системе, это была бы та же проблема. Три цифры дают вам тысячу адресов, если вы начинаете с нуля, но если вы начинаете с 1, вам нужно четыре цифры. Kaz 11 лет назад 0
1
9dan

Число 0 может обозначать различные значения: числовое значение, порядковый номер, адрес памяти и т. Д.

«Индекс ноль» не означает, что программисты считают с нуля. Он обозначает первое место выделенного блока памяти, а «0» - его адрес.

В C цикл через массив можно записать так:

int arr[N]; for (i=0; arr[N]; ++i) { ... } 

Такую же работу можно проделать в C #:

Object[] arr;  for (Object o in arr) { ... } 

Я думаю, что нет подсчета в обоих примерах.

1
TV's Frank

Начинать с нуля целесообразно при описании расстояния от чего-либо. Итак, в этом массиве:

[4,9,25,49]

расстояние от начала массива до 25 равно 2 - вам нужно пропустить два шага, чтобы добраться туда. Расстояние до 4 равно нулю - вам вообще не нужно двигаться с самого начала.

При сложении расстояний (или индексов) так думать целесообразно - я продвигаюсь на один шаг, затем на ноль, затем на два шага, где я? Я с индексом 1 + 0 + 2 = 3. Пропустив три шага, я получаю 49 в массиве выше.

Подсчет этажей в здании должен быть одинаковым (даже если мы не делаем это в США). Уровень земли должен быть нулевым, потому что вы не поднялись или не опустились; это стартовая позиция. 11 лет назад 0
Тем не менее, первый этаж - это первое, к чему вы пришли. Вы начинаете считать, когда входите в здание на первом этаже, и добавляете по мере подъема. Начинать с нуля имеет смысл, если вы считаете "в здании" состояние по умолчанию / нормальное / естественное состояние, что является интересным комментарием к городскому обществу. Ноль для уровня земли также имеет большой смысл, если несколько подуровней являются общими. 11 лет назад 0