Чому комп'ютери рахуються з нуля?


55

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

Які історичні причини для цього існують, і які практичні переваги має підрахунок від нуля над відрахуванням від одного?

Примітка. Це запитання вимагає чітко пояснених технічних відповідей, а не просто думок, і має на меті охопити комп'ютери загалом, а не просто програмування. Це питання поширюється на питання програмістів "Чому структури / масиви базуються на нулі?" .



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

Не дуже багато, але це додає зайвого віднімання для кожного доступу.

Редагувати

  • Використання індексу масиву як компенсації - це не вимога, а лише звичка. Зсув першого елемента може бути приховано системою і враховано при розподілі та посиланні на елемент.

  • Dijkstra опублікував документ "Чому нумерація повинна починатися з нуля" ( pdf ), де він пояснює, чому починати з 0 - це кращий вибір. Початок нуля дозволяє краще представити діапазони.


8
+1 за правильну відповідь. Зауважте, що індексація на основі 0 - це лише (дуже поширена) умова використовуваної мови; це не універсально. Наприклад, Lua використовує індексацію на основі 1 . Можливо, «непотрібне віднімання» було причиною індексації на основі 0 в старі часи, але зараз більшість мов використовують його просто тому, що це те, до чого всі вже звикли (значною мірою завдяки С) , і немає вагомих причин змінювати це конвенція.
BlueRaja - Danny Pflughoeft

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 - Danny Pflughoeft

3
Ні, це не питання про те, чи має масив нульовий елемент. Тому що, бачите, також існує масштабування. Якщо у мене є масив з 8-ти байтних об'єктів, і я накладаю його на байтовий масив, що таке байт-індекс об’єкта [42]? Чому це просто: 42 * 8. Проблема з 1 на основі полягає в тому, що це зміщення в 1 становить 1 байт, коли я дивлюся на байтовий масив, і це 8 байт, коли я дивлюся на накладений 8-байтовий масив.
Каз

38

Хоча наведені нижче принципи застосовуються як до десяткової, так і до будь-якої іншої основи, підрахунок від 0 у комп’ютерах легко зрозуміти природним чином із двійкової системи з фіксованою цифрою представлення чисел, що використовуються на комп'ютерах. Якщо у вас є 8 біт, то можна виразити 256 можливих комбінацій 1s і 0s. Ви можете використовувати ці 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 ні в один байт ви не змогли
OrangeDog

8
@Dougvj Нульовий підрахунок абсолютно не має нічого спільного з двійковим. Точка, яку ви робите, - це використовувати кожне число у фіксованому цифрі, що викликає занепокоєння незалежно від того, використовуєте ви базу 2, базу 10 або базу 23517.
Пітер Олсон,

2
-1 Це абсолютно не пов'язане з бінарним поданням.
BlueRaja - Danny Pflughoeft

26

Ніколи не думав, що можливість для такого філософа-крісла, як я, з’явиться на Суперусера. Тут є основна помилка, бо нефілософи схильні пропускати деталі. Якщо коротко: комп’ютери не рахуються з нуля, але номінал позицій починається від нуля.

Немає нічого заплутаного в цьому сприйнятому непослідовності між комп'ютерною та людською (будь-якою) технікою підрахунку. Розберемо питання.

Чому комп'ютери рахуються з нуля?

  • Вони не рахуються з нуля

Обчислювальні величини комп'ютерів, починаючи з нуля. Наприклад, масиви в C.

  • Індекс (індикатор положення, підрахунок) починається з нуля. Кількість елементів в масиві , де є один елемент з індексом нуль один

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

У тому ж сенсі, що і середня точка шкали, нуль можна використовувати для зображення самого краю (абсолютного початку) колекції. Питання є безглуздим, оскільки воно суперечить "підрахунковому значенню" та "рахунку від нуля".

Так, так, комп’ютери роблять підрахунок нуля, але вони рахуються з одного. Два слова мають різний зміст.

таллі [tal-ee]

іменник

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

рахувати [кількість]

дієслово (використовується з об’єктом)

  1. перевірити (окремі одиниці або групи колекції) по черзі, щоб визначити загальну кількість; складати; перерахуємо: Він порахував свої квитки і виявив, що у нього десять.
  2. рахуватися; розрахувати; обчислити.
  3. перелічити або назвати числівники до: Заплющить очі і порахуй десять.

(словник.com)


Практичні причини адекватно описані Дугвієм, мені тут нічого додати. Якби ми могли мати професора CS (з 60-х років), щоб дати історію ...


Насправді, як ви знаєте, звідки комп'ютер починає щось робити? Все, що ви знаєте, - це те, що коли ви його використовуєте, ви скажете це починати з нуля.
Даніель Р Хікс

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

1
Щоб бути повністю педантичним, ви порівнюєте дієслово з іменником. Я думаю, що "tally" і "count" насправді є синонімами, і обидва можуть використовуватися як дієслово, так і іменник.
Брайан

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

1
Просто дизайнери насправді розгулювали зовсім небагато, перш ніж влаштуватися на діючу схему. Те, що зараз здається "очевидним", не було. І, швидше за все, могла бути обрана дещо інша схема, яка зараз виглядатиме "очевиднішою", ніж у нас.
Даніель Р Хікс

12

Я думаю, що це раніше висвітлювалося " проф. Д-ром Edsger W. Dijkstra " - науковим співробітником Burroughs у листі від 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 (якщо явно не зазначено " від 0"), а з 1 для цілого випадку i в ~, ~, ~ esac і $ c (~, ~, ~ ) пропозиції щодо вибору $ .

Здається, що коментарі Дейкстри щодо проекту звіту за березень 1968 року ( MR93 ) та його наполягання спровокували те, що, мабуть, є попередньою полум'яною війною : "Є твори, які є приємними, хоча неграматичними, і є інші твори, які є надзвичайно граматичними, але є огидно. Це те, що я не можу пояснити поверховим особам ". EWD230

Остаточний звіт Algol 68 (FR) вийшов 20 грудня 1968 року, коли він був обурений на Мюнхенській нараді, а потім прийнятий Робочою групою. Згодом звіт, затверджений Генеральною Асамблеєю IFIP ЮНЕСКО для публікації.

Близько 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
@Jimmy Це була моя точка - якщо люди «підраховані від одного» в тому сенсі , що вони хочуть комп'ютери до, то вони будуть зараховуватися 2000 як один , а не як нуль. Це, до речі, те, як насправді це робили стародавні римляни (і справді описував би цикл на кшталт "2000, 2004, 2008" як п'ятирічний цикл).
Випадково832

2
Приклад вашого дня народження не є правдивим. Наприклад, у Південній Кореї перший рік життя зараховується як один, а не нульовий .
BennyMcBenBen

6

Як уже говорили інші, комп'ютери не рахуються з нуля .

Деякі мови індексують від 0. Індексація від 0 має дві основні переваги:

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

  2. Ви не отримуєте дивацтва, коли хочете негативу. Скільки років між 1BC та 1AD? Немає. Тому що хоча БК є фактично негативними датами, немає нуля року. Якби було 0AD, тут не було б жодних проблем. Ви бачите ту саму проблему всюди в науці, де люди наївно визначили перший елемент у наборі як +1.


Так, і вся дурість чекати до 2001 року нового тисячоліття. Це плутало саме тих людей, які також не "отримують" нульові масиви, коли вони спрацьовують у програмуванні. :)
Каз

3
Крім того, якщо "1 миля" означає "тут", то, оскільки миля становить 1760 футів, це означає, що "1760 футів" також означає "тут", правда? Неправильно, "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 на рівні програмного забезпечення для доступу до цього чіпа. Запит на слово 1 фактично поставить 00000000 на 8-бітну адресну шину. Або ж, запит 1 буде переводити на адресу 00000001, як і очікувалося, але запит на 256 відображалися б в іншому випадку невикористаної 8 бітний адреса 00000000 , а не 9 бітову адресу 100000000. Обидва цих мішків гризти кладжі дійсно рішення в пошук проблеми , і їх уникають повністю, послідовно використовуючи від 0 до 255 на апаратному забезпеченні, в програмному забезпеченні та в усіх користувальницьких інтерфейсах та документації.

Одномісні переміщення принципово дурні

Розглянемо, наприклад, західну теорію музики. У нас є діатонічні шкали із семи нотами, але ми називаємо простір, який вони охоплюють октавою ! Інверсія інтервалів слідує за правилом дев'яти : наприклад, інверсія третьої частини - шоста (віднімайте три з дев'яти). Отже, три різні числа грають для чогось такого простого: сім (ноти в масштабі), вісім (октава) і дев'ять (віднімання від до інвертування).

Якби сім нот складали септаву або гептаву, а інтервали були засновані на нулі, тоді ми віднімали б від семи до інвертування. Все на основі семи.

Крім того, інтервали можна легко складати. Якщо в поточній системі ми скачемо на п'яту, а потім на четверту, а потім на третю, ми не можемо просто їх додати. Отриманий інтервал на два менше. Це не дванадцята, а насправді десята! На кожному етапі ми повинні відняти один. Підйом на п'яту, а потім на четверту - це не дев'ята, а лише октава.

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

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

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

Коли 2000 рік прокотився, багато людей були розгублені, чому не почалося нове тисячоліття. Ті, хто вказує, що це не розпочнеться до 2001 року, розглядалися як мандрівники партії та опущення. Зрештою, вам 20 років, коли вам виповниться 20, правда? Не тоді, коли вам виповниться 21 рік. Якщо ви думали, що тисячоліття почалося 1 січня 2000 року, ви не маєте права скаржитися на нульові масиви будь-якою мовою програмування. Вони працюють, як саме вам подобається. (Але так, прихильники одноосновних переміщень та масивів - це опудала та партії-мандрівники. Століття повинні починатися з XX00 років, а тисячоліття - у X000 роках.)

Календарі німі, але принаймні час доби нульовий

Кожна нова хвилина на вашому годиннику починається з: 00 секунд. Кожна нова година починається з 00:00 хвилин і секунд. І, принаймні, на цілодобовому годиннику, день котиться, коли настає опівночі та з кроком 11:59:59 до 00:00:00.

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

Закриття про MIDI

Гаразд, що це з музикантами, навіть нібито технічними?

MIDI! Він використовує нульову нумерацію для програм і каналів у фактичному дротяному поданні повідомлень, але передач відображає його як 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-індекс, мали відношення до історичних причин. Algol-68, правнук мов програмування насправді був 1-індексованим, а також Fortran та ще декількома іншими "діловими" мовами на зразок COBOL. У деяких із цих мов, однак, ви можете чітко вказати, яким буде ваш початковий індекс. Там дуже цікава таблиця це тут .

В основному ще в " Євських днях " математики, вчені та інші "науковці" зазвичай використовували 0-індексовані мови, тоді як користувачі мов, таких як COBOL, вважають, що не потрібно починати рахувати 0, тому в цих мовах було більше сенсу почати з 1 (здавалося менш заплутаним).

Тепер, якщо ваше запитання стосується того, чому, наскільки комп'ютерне мова ), природно, починає рахуватися з нуля ... ну, мабуть, притаманне двійковій справді: наприклад: 0000нуль 0001= один ... так далі і так далі ...


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може зберігати, дорівнює 0. Якщо ми почали індекси масиву з 1, то система була б неефективною, оскільки тепер у нас є масив довжиною 255 замість 256. Оскільки числа в програмі С компілюються у двійкові числа ( 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 , 1 , n і т. Д. В іншому випадку потрібно часто коригувати +1 і –1, щоб отримати потрібні дані, і легко помилитися, створюючи помилки. Тому мови, призначені для вчених-комп’ютерів, зазвичай використовують натуральні числа: C, Java та Lisp - всі рахуються від 0.

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


Java ... для вчених-комп'ютерів. ЛОЛ!
Каз

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. Перший елемент розташований у місці Base, тому він знаходиться у розташуванні 0 (Base + 0).


0

Крім обчислювальної ефективності, існує ще один аспект підрахунку. Є два способи надати кожному елементу в послідовності послідовне число:

  1. Кількість попередніх (цілих) елементів (кардинальні номери)
  2. Положення елемента (порядкові числа)

Вік людей - це кардинальні цифри: у перший рік після народження дитини йому 0 років, тому що він жив уже нулі цілих років.

Роки в датах - порядкові числа: у перший рік Анно Доміні (н.е.) рік - 1 р. Н. Немає року 0, як і нічого нуля .

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


Звичайно, Маттео лише частково правильний, коли заявив, що індексація на основі нуля є більш ефективною.

element(n) = address + n * element_size

Одне засноване індексування може бути настільки ж ефективним за умови, що всі адреси масивів вже мають element_sizeвід них відняті. Це можна зробити при виділенні масиву, і в цьому випадку це так само швидко:

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

-1

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

0 ... Ви псуєте різні поняття: мови програмування, комп'ютери та підрахунок.

  1. Використання 2 станів (більшість із них схематично роблять саме це) означає, що ви можете вибрати 2 цифри для їх відображення (до, скажімо, посилань). "3" і "5" (або "F" і ",") було б нормально, але тоді ви запитаєте, чому комп'ютери рахуються з "3" (або від "F"). Природний вибір очевидно 0 і 1 очевидно.
  2. Масиви в Паскалі починаються з 1. Ця мова начебто абстрактніша, ніж на низькому рівні C.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.