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


55

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

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

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



9
Было более чем несколько примеров компьютерных языков, которые использовали массивы с 1 источником.
Даниэль Р Хикс

23
Почему люди не считают от 0?
Без названия

47
Вау, вау, никто не считает с нуля, мы индексируем с нуля. Никто не говорит "нулевой" элемент. Мы говорим «первый» элемент с индексом 0. Думайте об индексе как о смещении элемента от первой позиции. Итак, первый элемент находится на первой позиции, поэтому он вообще не смещен, поэтому его индекс равен 0. Второй элемент, как один элемент перед ним, поэтому он смещен на 1 элемент и имеет индекс 1
mowwwalker

14
@ Ramhound Нет, это не так. Индексирование на основе нуля совершенно не связано с использованием двоичного кода.
Питер Олсон

Ответы:


88

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

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

element(n) = address + n * size_of_the_element

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

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

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

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

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

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


8
+1 за правильный ответ. Обратите внимание, что индексирование на основе 0 - это просто (очень распространенное) соглашение об используемом языке; это не универсально. Например, Lua использует индексирование на основе 1 . «Ненужное вычитание» могло быть причиной индексации на основе 0 в старые времена, но сейчас большинство языков используют ее просто потому, что это то, к чему все уже привыкли (во многом благодаря C) , и нет веских причин для изменения этого условность.
BlueRaja - Дэнни Пфлугхофт

2
Это не имеет никакого смысла. Положение каждого элемента всегда может быть вычислено при address + n * size_of_elementусловии, что «адрес» - это адрес нулевого элемента. Это прекрасно работает независимо от того, существует ли нулевой элемент как элемент массива или нет. Вопрос в том, почему существует нулевой элемент, а не в том, почему мы храним адреса как адрес (возможно, условного) нулевого элемента. (На что это отвечает.)
Дэвид Шварц

3
@DavidSchwartz Давайте возьмем старый язык как C. Если выделить память, вы получите адрес, с которого начинается память. Если компилятор видит что-то подобное, v[n]он должен вычислить адрес выражения. Если индексы начинаются с 0, вычисление имеет размер v + x *. Если в 1 вычисление v + (x-1) * размер. Например, v [1] будет соответствовать размеру v + (1-1) *, то есть v.
Маттео

4
@David: В C (языке, который действительно популяризировал индексирование на основе 0) , массивы и указатели в значительной степени взаимозаменяемы, поэтому важно по ряду причин, которые *arrayфактически ссылаются на первый элемент. Один пример: если у нас есть arrayуказатель на ячейку памяти перед первым элементом, приведение к массиву другого типа будет проблематичным, например. позиция второго байта в массиве ints станет зависимой от размера слова; на 32-битной машине, это было бы в ((char*)intArray + 5)!!
BlueRaja - Дэнни Пфлугхофт

3
Нет, это не проблема того, имеет ли массив нулевой элемент. Потому что, вы видите, есть также масштабирование. Если у меня есть массив из 8-байтовых объектов, и я наложил его на байтовый массив, что такое байтовый индекс объекта [42]? Почему это просто: 42 * 8. Проблема с 1 на основе состоит в том, что это смещение 1 составляет 1 байт, когда я смотрю на массив байтов, и это 8 байтов, когда я смотрю на наложенный массив из 8 байтов.
Каз

38

Хотя приведенные ниже принципы применимы и к десятичной, и к любой другой базе, отсчет от 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 с вложенными структурами данных, как этот пример, может сбивать с толку.

31
Не имеет ничего общего с двоичным представлением. И двоичные, и десятичные числа начинаются с 0.
Маттео

2
Если вы начнете считать с 0, вы не уменьшите количество адресов, которые вы могли бы (теоретически) перейти с 1 на 257.
Маттео

6
@Matteo ни в одном байте вы не могли
Стоп Harming Моника

8
@Dougvj Подсчет на основе нуля не имеет абсолютно никакого отношения к двоичному. Суть того, что вы делаете, заключается в использовании каждого числа в представлении с фиксированной цифрой, что вызывает озабоченность независимо от того, используете ли вы базу 2, базу 10 или базу 23517.
Питер Олсон,

2
-1 Это не имеет ничего общего с двоичным представлением.
BlueRaja - Дэнни Пфлугхофт

26

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

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

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

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

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

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

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

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

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

tal·ly [tal-ee]

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

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

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

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

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

(Dictionary.com)


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


На самом деле, откуда вы знаете, где компьютер запускает что-нибудь? Все, что вы знаете, это то, что, когда вы используете это, вы говорите, чтобы начать с нуля.
Даниэль Р Хикс

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

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

1
@ Брайан Справедливое наблюдение, и я намерен проиллюстрировать (педантично), что путаница проистекает из неправильного толкования терминов. На самом деле нет разницы между «1-м элементом» и «элементом в позиции 0». Они оба элемент один. Во- первых , не " ноль ". Нет такой вещи, как считать с нуля . Перечисление начинается с единицы по определению, а адресация может быть a-> 1, b-> 2. с-> 3 или 0-> 1, 1-> 2, 2-> 3. Наиболее распространенный пример «отсчета с нуля» можно найти в математических книгах средней школы в виде {x₀, x₁, x₂} - но индекс - это индекс .

1
Просто дизайнеры действительно немного побродили, прежде чем остановились на текущей схеме. То, что кажется «очевидным», теперь не было. И, вероятно, могла бы быть выбрана несколько иная схема, которая теперь казалась бы более «очевидной», чем у нас.
Даниэль Р Хикс

12

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

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

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

"1 миля"

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

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

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

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

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

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


1
Ваша математика относительно выборов выключена на год. Ваш пример содержит 2 года выборов в течение 5 лет; правильной иллюстрацией будет то, что 4 года переходят от одного выбора к другому, то есть 2000 -> 2001 (1 год), 2001 -> 2002, 2002 -> 2003, 2003 -> 2004.
Джимми

1
@ Джимми Это была моя точка зрения - если бы люди «считали с одного» в том смысле, в каком они хотят компьютеров, они считали бы 2000 как одно, а не как ноль. Кстати, именно так на самом деле это делали древние римляне (и действительно описывали бы цикл, подобный «2000, 2004, 2008», как пятилетний цикл).
Random832

2
Пример вашего дня рождения не всегда правдив. Например, в Южной Корее первый год жизни считается одним, а не нулевым .
BennyMcBenBen

6

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

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

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

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


Да и вся глупость ждать до 2001 года нового тысячелетия. Это смутило именно тех людей, которые также не «получают» массивы, основанные на нуле, когда они увлекаются программированием. :)
Каз

3
Кроме того, если «1 миля» означает «прямо здесь», то, поскольку миля составляет 1760 футов, это означает, что «1760 футов» также означает «прямо здесь», верно? Неправильно, «1 фут» означает прямо здесь, ой! В одной этой основе глупости, «здесь» есть одна нога, один дюйм, один сантиметр, и т.д.
Kaz

1
@kaz где ноги => ярдов. 1760 ярдов в миле.
Брэд

3

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

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

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

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

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

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


4
Не имеет ничего общего с двоичным представлением. Как двоичные, так и десятичные числа начинаются с 0 (как показано в вашем примере).
Маттео

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

1

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

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

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

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

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

Object[] arr;

for (Object o in arr) {
...
}

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


1

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

[4,9,25,49]

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

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


Подсчет этажей в здании должен быть одинаковым (даже если мы не делаем это в США). Уровень земли должен быть нулевым, потому что вы не поднялись и не опустились; это стартовая позиция.

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

1

Помните, как числа представлены в компьютере. Давайте возьмем byteпеременную. 0 представляется как 00000000 1 в двоичном виде. 1 - 00000001. 2 - 00000010. И так далее.

Обратите внимание, что наименьшее число, которое byteможет хранить a, равно 0. Если бы мы начинали индексы массива с 1, то система была бы неэффективной, поскольку теперь у нас есть массив длиной 255 вместо 256. Поскольку числа в программе на C компилируются в двоичные числа ( intобычно unsigned ints в индексах массива), кажется естественным использовать 0 в качестве начального индекса, поскольку он более эффективен.

Кроме того, в C ++ a[p]разворачивается в *(a+p*n), где nразмер типа данных. Другими словами, a[p]означает «Дай мне элемент по индексу a+n*p». Если pначать с 1, то у нас будет пустая / неиспользованная часть в индексе a.

1. Конечно, возникает очевидный вопрос «почему». Почему бы не установить 00000000 на 1? Просто: двоичное сложение (выполняется каскадами полных сумматоров) легко в аппаратном обеспечении, когда 00000000 равно 0. Бинарное сложение является неотъемлемой частью всех арифметических операций. Если вы зададите значение 1, вам нужно будет либо указать компилятору вычесть 1 из всех чисел, либо вам нужно жестко связать схемы сумматоров, чтобы сначала вычесть одно из сумматоров и вернуть его обратно к сумме. (обратите внимание, что вы не можете просто вычесть один позже, так как может быть задействован бит переноса)


@sec, потому что это становится абсурдным на аппаратном уровне (см. редактирование)
Manishearth

1

Модульное

Одна вещь, о которой не говорится в существующих хороших ответах: индексирование с нуля хорошо работает вместе с операциями по модулю, которые поэтому могут быть объединены в циклический список. Например, подумайте о чем-то вроде

color = colors[i % colors.length]

что может дать каждому объекту (индексируемому i) другой цвет из списка colors, пока все цвета не будут использованы, после чего он начнется снова с самого начала. Выражать то же самое в индексации по одному довольно неуклюже:

color = colors[(i - 1) % colors.length + 1]

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

Обслуживает как

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


0

Компьютерные системы используют как натуральные числа (считая от 0), так и целые числа (считая от 1). Люди считают вещи целыми числами, что делает их интуитивно понятными для нумерации списков, и многие языки программирования используют это в своих интересах: BASIC, COBOL, Fortran, Lua и Pascal все считают от 1. Эти языки ориентированы на такие ниши, как обработка данных, численный анализ, и обучение, где простые, интуитивно понятные списки являются преимуществом.

Целые числа становятся неудобными, когда вы начинаете анализировать и манипулировать структурой данных, а не просто обрабатывать все по порядку. Когда вам нужно обратиться к последовательностям в формуле или алгоритме, проще и менее подвержено ошибкам нумеровать их от 0, как это делают математики: a 0 , a 1 , a n и т. Д. В противном случае вам часто приходится настраивать на +1 и –1, чтобы получить правильные данные, и легко ошибиться, создавая ошибки. Поэтому языки, разработанные для компьютерных специалистов, обычно используют натуральные числа: C, Java и Lisp, все считаются от 0.

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


Ява ... для компьютерщиков. ЛОЛ!
Каз

0

Ответ прост: первая цифра не 1, а 0.

Пояснение: Формула для расчета многозначного числа в любой базе:

n = sum(i=0 to n, Di^i)

WHERE 
n = numeric result
i = index (starting with 0)
Di = is the digit at index i

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

Глядя на число 1234, мы можем записать его как:

4 x 10^0 = 4
3 x 10^1 = 30
2 x 10^2 = 200
1 x 10^3 = 1000

in other words, sum of digits raised to the power if their index.

Так что это не только компьютеры, мы, люди, тоже считаем от 0.


0

Индекс массива - это смещение от базовой ячейки памяти до ячейки памяти элемента. Элемент i является тогда Base + i. Первый элемент расположен в базовом местоположении, поэтому он находится в местоположении 0 (Base + 0).


0

Помимо вычислительной эффективности, есть еще один аспект подсчета. Есть два способа присвоить каждому элементу последовательности порядковый номер:

  1. Количество предшествующих (целых) элементов (кардинальных чисел)
  2. Положение элемента (порядковые номера)

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

Годы в датах являются порядковыми номерами: в первом году Anno Domini (AD), год - 1 нашей эры. Нет нулевого года, как нет ничего нулевого .

Языки программирования (такие как Matlab и Mathematica), где индекс элемента представляет его позицию в массиве, начинают считать с 1: первый элемент. В других языках (таких как все языки на основе C) индекс элемента - это число предшествующих элементов, и поэтому первый элемент равен 0.


Конечно, Matteo только частично прав, утверждая, что индексация на основе нуля более эффективна.

element(n) = address + n * element_size

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

array_address = address - element_size
element(n) = array_address + n * element_size

-1

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

0… Вы путаете разные понятия: языки программирования, компьютеры и счет.

  1. Использование 2 состояний (большинство из них схематически делают именно это) означает, что вы можете выбрать 2 цифры, чтобы сопоставить их (скажем, для ссылки). «3» и «5» (или «F» и «,») будут в порядке, но тогда вы спросите, почему компьютеры считают «3» (или «F»). Естественный выбор 0 и 1, очевидно.
  2. Массивы в Паскале начинаются с 1. Этот язык более абстрактный, чем низкоуровневый Си.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.