Perché i computer contano da zero?


55

I computer tradizionalmente calcolano i valori numerici a partire da zero. Ad esempio, le matrici nei linguaggi di programmazione basati su C iniziano dall'indice zero.

Quali ragioni storiche esistono per questo e quali vantaggi pratici ha il conteggio da zero rispetto al conteggio da uno?

Nota: questa domanda richiede risposte tecniche ben spiegate, non solo opinioni, ed è destinata a coprire i computer in generale piuttosto che solo la programmazione. Questa domanda si espande sulla domanda dei programmatori "Perché le strutture / matrici sono basate su zero?" .



9
Ci sono stati più di alcuni esempi di linguaggi informatici che utilizzavano array a 1 origine.
Daniel R Hicks,

23
Perché gli umani non contano da 0?
Senza titolo

47
Woah, woah, nessuno conta da zero, indicizziamo da zero. Nessuno dice l'elemento "zeroth". Diciamo il "primo" elemento all'indice 0. Pensa all'indice come quanto un elemento è spostato dalla prima posizione. Bene, il primo elemento è nella prima posizione, quindi non è affatto sfalsato, quindi il suo indice è 0. Il secondo elemento come un elemento prima di esso, quindi è sfalsato 1 elemento ed è nell'indice 1
mowwwalker

14
@Ramhound No, non lo è. L'indicizzazione in base zero non è completamente correlata all'utilizzo del binario.
Peter Olson,

Risposte:


88

Il conteggio di matrici da 0 semplifica il calcolo dell'indirizzo di memoria di ciascun elemento.

Se un array è memorizzato in una data posizione nella memoria (si chiama indirizzo), la posizione di ciascun elemento può essere calcolata come

element(n) = address + n * size_of_the_element

Se si considera il primo elemento il primo, il calcolo diventa

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

Non molto diverso, ma aggiunge una sottrazione non necessaria per ogni accesso.

modificare

  • L'uso dell'indice di array come offset non è un requisito ma solo un'abitudine. L'offset del primo elemento potrebbe essere nascosto dal sistema e preso in considerazione durante l'allocazione e il riferimento dell'elemento.

  • Dijkstra ha pubblicato un articolo "Perché la numerazione dovrebbe iniziare da zero" ( pdf ) in cui spiega perché iniziare con 0 è una scelta migliore. Iniziare da zero consente una migliore rappresentazione degli intervalli.


8
+1 per la risposta corretta. Si noti che l'indicizzazione basata su 0 è solo una convenzione (molto comune) della lingua utilizzata; non è universale. Ad esempio, Lua utilizza l'indicizzazione basata su 1 . La "sottrazione non necessaria" potrebbe essere stata il ragionamento alla base dell'indicizzazione basata su 0 ai vecchi tempi, ma ora la maggior parte delle lingue lo utilizza semplicemente perché è ciò a cui tutti sono già abituati (in gran parte grazie a C) , e non c'è motivo convincente per cambiarlo convenzione.
BlueRaja - Danny Pflughoeft il

2
Questo non ha senso. La posizione di ciascun elemento può sempre essere calcolata address + n * size_of_elementpurché "indirizzo" sia l'indirizzo dell'elemento zeroth. Funziona perfettamente indipendentemente dall'elemento zeroth come elemento dell'array. La domanda è: perché esiste l'elemento zeroth, non perché memorizziamo gli indirizzi come l'indirizzo (possibilmente nozionale) di zeroth. (Che risponde.)
David Schwartz,

3
@DavidSchwartz Prendiamo una vecchia lingua come C. Se allocare memoria si ottiene un indirizzo dove inizia la memoria. Se un compilatore vede qualcosa di simile v[n], deve calcolare l'indirizzo dell'espressione. Se gli indici iniziano con 0, il calcolo è v + x *. Se a 1 il calcolo è v + (x-1) * dimensione. Ad esempio, v [1] corrisponderà alla dimensione v + (1-1) * che è v.
Matteo

4
@David: in C (il linguaggio che ha reso molto popolare l'indicizzazione basata su 0) , le matrici e i puntatori sono in gran parte intercambiabili, quindi è importante per una serie di ragioni che si *arrayriferiscono effettivamente al primo elemento. Un esempio: se abbiamo arraypuntato sulla posizione della memoria prima del primo elemento, eseguire il casting su un array di un tipo diverso sarebbe problematico, ad es. la posizione del secondo byte in una matrice di ints diventerebbe dipendente dalla dimensione della parola; su una macchina a 32 bit, sarebbe a ((char*)intArray + 5)!!
BlueRaja - Danny Pflughoeft il

3
No, questo non è un problema se l'array ha un elemento zeroth. Perché, vedi, c'è anche il ridimensionamento. Se ho una matrice di oggetti a 8 byte e la sovrappongo a una matrice di byte, qual è l'indice di byte dell'oggetto [42]? Perché è semplice: 42 * 8. Il problema con 1 basato è che questo offset di 1 è 1 byte quando guardo l'array di byte, ed è 8 byte quando guardo l'array di unità a 8 byte sovrapposto.
Kaz,

38

Mentre i principi seguenti si applicano sia ai decimali che a qualsiasi altra base, il conteggio da 0 nei computer può essere facilmente compreso naturalmente dal sistema binario a cifre fisse di rappresentazione dei numeri utilizzati nei computer. Se hai 8 bit, allora ci sono 256 possibili combinazioni di 1 e 0 che possono essere espresse. Potresti usare questi 8 bit per esprimere i numeri 1-256, ma questo tralascerebbe 0 che è utile in matematica come numero in sé e per sé, quindi sono usati per esprimere i numeri 0-255.

Questo imposta già un precedente di un ordine naturale a partire da 0 (tutti gli 0 nella rappresentazione binaria) a 255 (tutti gli 1 in un numero a 8 bit). Considerando il sistema di rappresentazione dei numeri, a partire da 0 ha senso perché 0 è il "primo" numero nel sistema, quindi 1 è il "secondo" numero e così via.

Un ulteriore motivo per cui partire da 0 nei computer è così conveniente è dovuto al concetto di offset. Un offset è un numero che rappresenta la distanza da una posizione in memoria o disco rigido o qualsiasi altro supporto "indirizzabile". Nei computer, praticamente tutti i dati sono memorizzati in modo lineare, il che significa che esiste un ordine per i dati, un primo un byte, un secondo byte, ecc. È conveniente esprimere la posizione di "aree" dei dati tramite un offset. Qual è il primo byte in un blocco di dati? È all'offset '0', il che significa che viene trovato 0 byte dopo il primo byte nel blocco di dati. Mentre è possibile avere "1" designare il primo byte, ciò crea complicazioni nella rappresentazione dei dati per diversi motivi:

  • Escludendo 0 dall'uso per indirizzare i dati, riduci di uno il numero di cose che puoi affrontare con un numero a 8 bit.
  • Per calcolare l'offset, necessario a livello hardware dell'accesso ai dati, a un certo punto è necessario sottrarre uno dalla numerazione, il che introduce una complessità.
  • I puntatori a un blocco di dati puntano sempre al primo blocco, quindi l'aritmetica è semplice quando si inizia da 0. (ovvero, il 1 ° byte nel primo blocco del primo cluster di dati è 0 + 0 + 0 quando si inizia da 0 , è 1 + 1 + 1 - 1 -1 quando inizi da 1.) L'aritmetica per questo quando inizi da 1 con strutture di dati nidificate come questo esempio può essere fonte di confusione.

31
Non ha nulla a che fare con la rappresentazione binaria. I numeri binari e decimali iniziano da 0.
Matteo

2
Se inizi a contare da 0 non riduci il numero di indirizzi che potresti (in teoria) passare da 1 a 257.
Matteo

6
@Matteo non in un singolo byte che non potresti
Smetti di danneggiare Monica il

8
@Dougvj Il conteggio basato su zero non ha assolutamente nulla a che fare con il binario. Il punto che stai prendendo in considerazione riguarda l'uso di ogni numero in una rappresentazione a cifre fisse, il che è una preoccupazione indipendentemente dal fatto che tu stia usando la base 2, la base 10 o la base 23517.
Peter Olson,

2
-1 Non ha assolutamente nulla a che fare con la rappresentazione binaria.
BlueRaja - Danny Pflughoeft il

26

Non avrei mai pensato che un'occasione per un filosofo poltrona come me sarebbe arrivata su Superuser. C'è un malinteso fondamentale nel cuore qui, perché i non filosofi tendono a saltare i minimi dettagli. In breve: i computer non contano da zero, ma la denominazione delle posizioni inizia da zero.

Non c'è nulla di confuso in questa percepita incoerenza tra le tecniche di conteggio del computer e quella umana (qualsiasi). Decomponiamo la domanda.

Perché i computer contano da zero?

  • Non contano da zero

I valori di conteggio dei computer partono da zero. Ad esempio, matrici in C.

  • L' indice (indicatore di posizione, conteggio) inizia da zero. Il conteggio degli elementi in un array in cui è presente un singolo elemento nell'indice zero è uno

Zero è pratico per rappresentare un vuoto di qualcosa o il punto medio di una scala. Non è pratico per contare qualcosa perché è impossibile per definizione di zero.

Nello stesso senso del punto centrale di una scala, lo zero può essere utilizzato per rappresentare il bordo (inizio assoluto) di una raccolta. La domanda non ha senso perché è incoerente tra "valori di conteggio" e "conta da zero".

Quindi sì, i computer calcolano da zero, ma contano da uno. Le due parole hanno un significato diverso.

tal·ly [tal-ee]

sostantivo

  1. un conto o una resa dei conti; un registro di debito e credito, del punteggio di una partita o simili.
  2. qualsiasi cosa su cui viene mantenuto un punteggio o un account ..
  3. un numero o un gruppo di elementi registrati.

count [kount]

verbo (usato con l'oggetto)

  1. controllare (le unità o i gruppi separati di una raccolta) uno per uno per determinare il numero totale; addizionare; enumerare: contò i suoi biglietti e scoprì che ne aveva dieci.
  2. fare i conti; calcolare; calcolare.
  3. per elencare o nominare i numeri fino a: Chiudi gli occhi e conta dieci.

(Dictionary.com)


Le ragioni pratiche sono adeguatamente descritte da Dougvj, non ho nulla da aggiungere lì. Se solo potessimo avere un professore CS (degli anni '60) per fare un resoconto storico ...


In effetti, come fai a sapere dove il computer avvia qualcosa? Tutto quello che sai è che, quando lo usi, DIRE che inizia da zero.
Daniel R Hicks,

Sto parlando di definizioni di concetti e logica qui, non di come i computer funzionano di per sé. Conosco un po 'dove i computer iniziano qualsiasi cosa perché ho seguito corsi CS.
Ярослав Рахматуллин,

1
Per essere completamente pedante, stai confrontando un verbo con un sostantivo. Penso che "tally" e "count" siano davvero sinonimi, ed entrambi possono essere usati come verbo o sostantivo.
Brian,

1
@Brian Un'osservazione equa e la mia intenzione è quella di illustrare (in modo pedante) che la confusione deriva da una errata interpretazione dei termini. Non c'è davvero alcuna differenza tra "il 1 ° elemento" e "l'elemento in posizione 0". Sono entrambi elemento uno. Il primo , non " zeroth ". Non esiste un conteggio da zero . L'enumerazione inizia da una per definizione, mentre l'indirizzamento può essere a-> 1, b-> 2. c-> 3 o 0-> 1, 1-> 2, 2-> 3. L'esempio più comune di "contare da zero" può essere trovato nei libri di matematica della scuola media sotto forma di {x₀, x₁, x₂} - ma il pedice è un indice .

1
È solo che i designer hanno vagato un po 'prima di decidere sullo schema attuale. Ciò che sembra "ovvio" ora non lo era. E probabilmente uno schema alquanto diverso avrebbe potuto essere scelto e ora sembrerebbe più "ovvio" di quello che abbiamo.
Daniel R Hicks,

12

Penso che questo sia stato trattato in precedenza dal " prof.Dr. Edsger W. Dijkstra " - Burroughs Research Fellow in una lettera dell'11 agosto 1982: cfr EWD831

Intitolato: perché la numerazione dovrebbe iniziare da zero . "Ci sono ragioni per preferire una convenzione all'altra? Sì, ci sono ...."

Si noti inoltre che Dijkstra faceva parte del team di progettazione ALGOL 68 fino alla fine del 1968. Algol68 consente array da 0, 1 o qualsiasi numero che il programmatore ritenga appropriato per l'algoritmo. cf ( "The Making of Algol 68" racconta "" Riesci a definire array triangolari? "qualcuno interruppe (Tony Hoare?)" Non solo triangolare, ma anche ellittico "rispose Aad e mostrò come."

In particolare, in Algol68, quando le matrici (e le matrici) vengono tagliate ottengono un indice @ 1, quindi c'è una propensione verso le matrici [1: ...]. Ma il "1 ° " limite inferiore può essere spostato per iniziare a "0 ° " posizione indicando "@ 0", ad esempio vettore x [4: 99 @ 2], matrice y [4: 99 @ 1,4: 99 @ 0]. Allo stesso modo c'è un default / bias di da 1 nei cicli do ~ od (a meno che " da 0" non sia esplicitamente dichiarato), e da 1 per il caso intero i in ~, ~, ~ esac e $ c (~, ~, ~ ) $ clausole choice .

Sembra che i commenti di Dijkstra sul Draft Report del marzo 1968 ( MR93 ) e le sue insistenze abbiano provocato quella che è probabilmente una guerra di fiamma pre-usenet : "ci sono scritti che sono adorabili anche se non grammaticali, e ci sono altri scritti che sono estremamente grammaticali, ma lo sono disgustoso. Questo è qualcosa che non posso spiegare alle persone superficiali ". EWD230

La relazione finale Algol 68 (FR) è stata pubblicata il 20 dicembre 1968, quando è stata risentita alla riunione di Monaco e successivamente adottata dal gruppo di lavoro. Successivamente il rapporto è stato approvato dall'Assemblea Generale dell'IFIP dell'UNESCO per la pubblicazione.

Intorno al 23 dicembre (?) 1968 Dijkstra, Duncan, Garwick, Hoare , Randell , Seegmuller, Turski, Woodger e Garwick firmarono il "Rapporto sulle minoranze" AB31.1.1.1, pagina 7 (pubblicato 1970).


10

L'analogia della distanza che qualcun altro ha sollevato si presta a un'illustrazione molto pratica:

"Quanto dista casa dalla stazione di benzina più vicina?"

"1 miglio."

"Vivi alla stazione di benzina?"

"No, se vivessi alla stazione di servizio sarebbe 0 miglia"

"Perché conti da zero invece che da uno?"

Un altro buon esempio potrebbero essere i compleanni: non diciamo che qualcuno abbia un anno il giorno in cui sono nati, diciamo che è un anno dopo.

Diciamo che gli anni bisestili o le elezioni presidenziali degli Stati Uniti sono ogni quattro anni, anche se si conta da uno: 2000 , 2001, 2002, 2003, 2004 sono cinque anni. (Per inciso, i romani hanno rovinato tutto per un po 'e hanno fatto anni bisestili troppo vicini)

Il mio punto è che "contiamo" sempre da zero nel mondo reale - "Quante posizioni dopo [inizio dell'array] è l'elemento che vuoi" sembra semplicemente essere la domanda a cui stai rispondendo con un conteggio da zero in molti programmi per computer. Non diresti che il primo elemento è una posizione dopo l'inizio, vero? Si è l'inizio.


1
La tua matematica relativa alle elezioni termina di un anno. Il tuo esempio contiene 2 anni elettorali nell'arco di 5 anni; l'illustrazione corretta sarebbe che 4 anni passano da un'elezione alla successiva, ovvero 2000 -> 2001 (un periodo di 1 anno), 2001 -> 2002, 2002 -> 2003, 2003 -> 2004.
Jimmy

1
@Jimmy Quello era il mio punto : se le persone "contano da uno" nel senso in cui vogliono i computer, contano 2000 come uno invece che come zero. Questo è, per inciso, il modo in cui gli antichi romani lo facevano effettivamente (e in effetti descrivono un ciclo come "2000, 2004, 2008" come un ciclo di cinque anni).
Casuale 832

2
Il tuo esempio di compleanno non è universalmente vero. Ad esempio, in Corea del Sud il primo anno di vita è contato come uno anziché zero .
BennyMcBenBen,

6

Come già detto da altri computer non contano da zero .

Alcune lingue indicizzano da 0. L'indicizzazione da 0 ha due vantaggi principali:

  1. Converte in assembly in modo naturale perché può essere interpretato come un offset da un puntatore alla prima posizione.

  2. Non ottieni stranezze quando vuoi negativi. Quanti anni tra 1BC e 1AD? Nessuna. Perché sebbene BC sia effettivamente date negative, non c'è anno zero. Se ci fosse stato 0AD non ci sarebbero stati problemi qui. Vedi lo stesso problema ovunque nella scienza in cui le persone hanno ingenuamente definito il primo elemento di un set come +1.


Sì, e tutta la stupidità dell'attesa fino al 2001 per il nuovo millennio. Ciò ha confuso esattamente quelle persone che non "ottengono" array a base zero quando si dilettano nella programmazione. :)
Kaz,

3
Inoltre, se "1 miglio" significa "proprio qui", quindi poiché un miglio è 1760 piedi, significa che "1760 piedi" significa anche "proprio qui", giusto? Sbagliato, "1 piede" significa proprio qui, oops! In questa stupidità basata su questo, "proprio qui" è un piede, un pollice, un centimetro, ecc.
Kaz

1
@kaz dove piedi => iarde. 1760 iarde in un miglio.
Brad,

3

Il conteggio inizia naturalmente da zero

Ecco l'algoritmo per contare le mele in un cestino:

count := 0

for each apple in basket
   count := count + 1

Dopo l'esecuzione di quanto sopra, countdetiene il numero di mele. Può essere zero, perché i cestini possono essere vuoti.

Se non usi la tua carta di credito per un mese intero, ricevi una fattura di 1 dollaro? O 1 centesimo?

Quando ripristini il contachilometri sul contachilometri della tua auto, passa a 0001 o 0000?

Le matrici possono fornire più viste degli stessi dati

Considera una matrice di strutture a 32 bit d, ciascuna composta da parole a 16 bit w. Ogni parola è composta da due byte a 8 bit b. Sotto indicizzazione zero, l'overlay sembra molto conveniente:

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

L'oggetto a 32 bit d[1]come all'indirizzo della parola w[2]che viene facilmente calcolato moltiplicando l'indice per 2, che è il rapporto tra le dimensioni dell'oggetto a 32 e 16 bit. Inoltre, nell'indirizzamento dei byte, lo è b[4].

Questo funziona perché zero è zero, in ogni unità di misura: byte, parola, doppia parola e così via.

Guarda il diagramma sopra: sembra molto simile a un righello, in cui le conversioni di unità sono intuitive.

Con un'indicizzazione basata, si rompe:

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

Ora non possiamo semplicemente moltiplicare l' dindice per 2 per ottenere l' windice o per 4 per ottenere l' bindice. La conversione tra unità diventa goffa. Per esempio per andare da d[2]a b[4], dobbiamo calcolare ((2 - 1) * 4) + 1 = 5.

Dobbiamo sottrarre quel fastidioso pregiudizio 1 nelle dunità, quindi eseguire il ridimensionamento nel sistema di coordinate naturale basato su zero, quindi aggiungere nuovamente il fastidioso 1 in bunità. Nota che non è lo stesso 1! Sottraiamo una larghezza di una parola doppia, ma poi aggiungiamo una larghezza di un byte .

La conversione tra diverse visualizzazioni dei dati diventa qualcosa di simile alla conversione Celsius-Fahrenheit.

Coloro che affermano che gli array a una base sono facili da gestire a livello di implementazione, poiché esiste solo una semplice sottrazione di 1, stanno prendendo in giro se stessi e te. Questo è vero solo se non eseguiamo calcoli di ridimensionamento tra diversi tipi di dati. Tali calcoli avvengono in qualsiasi programma che abbia una visione flessibile dei dati (ad es. Un array multidimensionale accessibile anche come monodimensionale) o che manipoli l'archiviazione: ad esempio un allocatore di memoria, un file system o una libreria di buffer di frame video.

Cifre minimizzanti

In qualsiasi base, se vogliamo usare il minor numero di cifre per implementare un intervallo di valori che è una potenza della base, dobbiamo iniziare da zero. Ad esempio, nella base dieci, sono sufficienti tre cifre per darci un migliaio di valori distinti da 0 a 999. Se iniziamo da 1, trabocchiamo di un solo valore e abbiamo bisogno di quattro cifre.

Ciò è importante nei computer, poiché il numero di cifre in binario si traduce in righe dell'indirizzo hardware. Ad esempio, un chip ROM con 256 parole può essere indirizzato da 0 a 255, che richiede 8 bit: da 00000000 a 11111111. Se viene indirizzato da 1 a 256, sono necessari nove bit. Dobbiamo aggiungere inutilmente un'altra traccia di indirizzo al circuito o al circuito integrato. Quindi ciò che potrebbe accadere in pratica sarebbe che 0 sarebbe semplicemente chiamato1 a livello di API software per l'accesso a quel chip. Una richiesta per la parola 1 inserisce effettivamente 00000000 nel bus degli indirizzi a 8 bit. Altrimenti, una richiesta per 1 si tradurrebbe all'indirizzo 00000001, come previsto, ma una richiesta per 256 verrebbe associata all'indirizzo a 8 bit altrimenti inutilizzato 00000000 anziché all'indirizzo a 9 bit 100000000. Entrambi questi kludges bag-biting sono davvero soluzioni in ricerca di un problema , e vengono completamente evitati utilizzando costantemente da 0 a 255 nell'hardware, nel software e in tutte le interfacce utente e documentazione.

Gli spostamenti a base singola sono fondamentalmente stupidi

Considera la teoria della musica occidentale per esempio. Abbiamo scale diatoniche con sette note, ma chiamiamo lo spazio che coprono un'ottava ! L'inversione degli intervalli segue quindi la regola del nove : ad esempio l'inversione di un terzo è un sesto (sottrarre tre da nove). Quindi tre diversi numeri sono in gioco per qualcosa di così semplice: sette (note in scala), otto (ottava) e nove (sottrarre da per invertire).

Se sette note formassero una setta o un'ottava e gli intervalli fossero basati su zero, sottrarremmo da sette a invertiti. Tutto basato su sette.

Inoltre, gli intervalli potrebbero essere facilmente impilati. Nel sistema attuale, se saltiamo di un quinto e poi di nuovo di un quarto, e poi di un terzo, non possiamo semplicemente aggiungerli. L'intervallo risultante è due in meno. Non è un dodicesimo, ma in realtà un decimo! In ogni fase, dobbiamo sottrarre uno. Salire di un quinto e poi di un quarto non è un nono, ma solo un'ottava.

In un sistema musicale progettato in modo sano, potremmo semplicemente aggiungere intervalli per determinare i salti risultanti. Una sequenza di note che inizia e finisce sulla stessa nota avrebbe quindi una proprietà simile alla legge della tensione attorno a un circuito: tutti gli intervalli si sommerebbero a zero.

La teoria e la scrittura della musica sono molto obsolete. La maggior parte non è cambiata dai tempi in cui la composizione era fatta con penne d'oca alla luce di una candela.

I sistemi a base unica confondono le stesse persone che non sono in grado di gestire matrici a base zero

Quando è iniziato il 2000, molte persone erano confuse sul perché il nuovo millennio non è iniziato. Coloro che hanno sottolineato che non inizierà fino al 2001 sono stati considerati cacca di partito e abitanti. Dopo tutto, hai compiuto 20 anni quando compi 20 anni, giusto? Non quando compirai 21 anni. Se pensavi che il millennio fosse iniziato il 1 ° gennaio 2000, allora non hai il diritto di lamentarti di array a base zero in qualsiasi linguaggio di programmazione. Funzionano esattamente come ti piace. (Ma sì, i sostenitori degli spostamenti e degli array basati su una sola base sono dweebs e pop-poopers. I secoli dovrebbero iniziare negli anni XX00 e millenni negli X000 anni.)

I calendari sono stupidi, ma almeno l'ora del giorno è a base zero

Ogni nuovo minuto sull'orologio inizia con: 00 secondi. Ogni nuova ora inizia con 00:00 minuti e secondi. E, almeno su un orologio di 24 ore, il giorno scorre intorno quando scatta la mezzanotte e 11:59:59 passa alle 00:00:00.

Quindi, se vuoi calcolare i secondi da mezzanotte per un tempo come 13:53:04, devi solo valutare 13 * 3600 + 53 * 60 + 4. Nessuna 1aggiunta o sottrazione insipida .

Rant di chiusura su MIDI

Ok, che succede con i musicisti, anche quelli presumibilmente tecnici?

MIDI! Utilizza la numerazione in base zero per programmi e canali nella rappresentazione filo reale dei messaggi, ma gear lo mostra come 1 basato! Ad esempio, i programmi da 0 a 127 sono chiamati da 1 a 128 sulla maggior parte degli ingranaggi, ma alcuni li chiamano da 0 a 127 o addirittura offrono all'utente una scelta.

I programmi da 71 a 80 sono considerati una "banca" di dieci. Lo dice proprio sul mio pedale MIDI, per esempio. Gli interruttori a pedale sono etichettati da 1 a 10 e se sono nel settimo banco, selezionano i programmi da 71 a 80. Tuttavia, alcuni dispositivi o software visualizzano i numeri di programma 1-128 come da 0 a 127, o forniscono all'utente un scelta! Cosa c'è di peggio: sistemi basati su uno o caos creati usando contemporaneamente uno e uno zero?

I numeri dei canali MIDI sono chiamati da 1 a 16, ma sono rappresentati da 0 a 15 binari. Come per dispetto per la presentazione a base singola, alcuni dispositivi utilizzano un dispswitch per configurare un numero di canale e, spesso, questi switch usano solo il codice binario a base zero. Quindi, se si desidera il canale 3, è necessario impostarlo su 0010 (binario 2).


1

Se ricordo correttamente dalla mia classe di concetti di linguaggio di programmazione ... i linguaggi indicizzati come 0 e gli altri che avevano un indice avevano a che fare con ragioni storiche. Algol-68, il nonno dei linguaggi di programmazione era in realtà indicizzato 1, così come Fortran e alcuni altri linguaggi "commerciali" come COBOL. In alcune di queste lingue, tuttavia, potresti effettivamente specificare esplicitamente quale sarebbe l'indice di partenza. C'è una tabella interessante di questo qui .

Fondamentalmente in " Ye Olde Days " i matematici, gli scienziati e altri "accademici" usavano di solito lingue con indice 0, mentre gli utenti di lingue come COBOL trovavano inutile iniziare a contare a 0, quindi in quelle lingue aveva più senso per iniziare da 1 (sembrava meno confuso).

Ora, se la tua domanda si riferisce al perché, per quanto riguarda il motivo per cui un computer ( non un linguaggio ) inizia naturalmente a contare da zero ... beh, immagino sia inerente al binario davvero: es: 0000= zero 0001= uno ... così via e così via via...


4
Non ha nulla a che fare con la rappresentazione binaria. I numeri binari e decimali iniziano da 0 (come mostrato nell'esempio).
Matteo,

Bene, ha qualcos'altro a che fare con il binario. Con quattro bit, da 0000 a 1111, è possibile indirizzare un banco di memoria di 16 parole. Se lo fai su una base, allora hai bisogno di cinque linee di indirizzo per rappresentare da 0001 a 10000. Altrimenti fai quello che, ad esempio, il MIDI fa con i numeri di canale: 0000 viene utilizzato internamente, ma le interfacce utente mostrano 1! Se l'hardware fosse basato su decimali, sarebbe lo stesso problema. Tre cifre ti danno un migliaio di indirizzi se inizi da zero, ma se inizi da 1, hai bisogno di quattro cifre.
Kaz,

1

Il numero 0 potrebbe indicare vari significati: valore numerico, ordinale, indirizzo di memoria, ecc.

"Indice zero" non significa che i programmatori contano da zero. Indica il primo posto di un blocco di memoria allocato e "0" ne è l'indirizzo.

In C, il ciclo attraverso un array può essere scritto come di seguito:

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

Lo stesso lavoro può essere fatto in C #:

Object[] arr;

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

Penso che non sia possibile contare in entrambi gli esempi.


1

Iniziare da zero è pratico quando si descrive una distanza da qualcosa. Quindi in questo array:

[4,9,25,49]

la distanza tra l'inizio dell'array e il 25 è 2 - per arrivarci devi saltare due passaggi. La distanza dal 4 è zero: non è necessario spostarsi dall'inizio.

È pratico pensare in questo modo quando si sommano le distanze (o gli indici) - Avanzamento di un passo, quindi zero passi, quindi due passi, dove sono? Sono all'indice 1 + 0 + 2 = 3. Saltando tre passaggi, finisco con 49 nell'array sopra.


Contare i piani di un edificio dovrebbe essere davvero allo stesso modo (anche se non lo facciamo negli Stati Uniti) Il livello del suolo dovrebbe essere zero perché non sei salito o sceso; è una posizione di partenza.

Eppure il piano terra è il primo che vieni. Inizi a contare quando entri nell'edificio, al piano terra, e aggiungi mentre sali. Iniziare da zero ha senso se si considera "in un edificio" lo stato predefinito / normale / naturale, che è un commento interessante sulla società urbana. Lo zero per il livello del suolo ha anche molto senso se sono comuni più sotto-livelli.

1

Ricorda come sono rappresentati i numeri in un computer. Prendiamo una bytevariabile. 0 è rappresentato come 00000000 1 in binario. 1 è 00000001. 2 è 00000010. E così via.

Si noti che il numero più basso che bytepuò essere archiviato è 0. Se iniziassimo gli indici di array con 1, il sistema sarebbe inefficiente, poiché ora abbiamo un array di lunghezza 255 anziché 256. Poiché i numeri in un programma C vengono compilati in numeri binari ( ints di solito, unsigned ints in indici di array), sembra naturale usare 0 come indice iniziale in quanto è più efficiente.

Inoltre, in C ++, a[p]si svolge *(a+p*n)dove si ntrova la dimensione del tipo di dati. In altre parole, a[p]significa "Dammi l'elemento all'indice a+n*p". Se piniziato con 1, allora avremmo una parte vuota / non utilizzata all'indice a.

1. Naturalmente, sorge l'ovvia domanda "perché". Perché non impostare 00000000 su 1? Semplice: l'aggiunta binaria (eseguita a cascata di unità adder complete) è semplice nell'hardware quando 00000000 è 0. L'aggiunta binaria è parte integrante di tutte le operazioni aritmetiche. Se lo fai rappresentare 1, dovresti o dire al compilatore di sottrarre 1 da tutti i numeri, o dovresti cablare i circuiti dei sommatori per sottrarre uno dai addend e fissarlo nuovamente alla somma. (nota che non puoi sottrarre uno in seguito, poiché potrebbe essere coinvolto il bit di riporto)


@sec perché diventa assurdo a livello hardware (vedi modifica)
Manishearth

1

Modulo

Una cosa che le buone risposte esistenti non menzionano ancora: l'indicizzazione a base zero funziona bene insieme alle operazioni del modulo, che possono quindi essere combinate per formare un elenco ciclico. Pensa ad esempio a qualcosa del genere

color = colors[i % colors.length]

che potrebbe dare a ciascun oggetto (indicizzato da i) un colore diverso dall'elenco colors, fino a quando non saranno stati utilizzati tutti i colori, a quel punto ricomincerebbe dall'inizio. Esprimere lo stesso nell'indicizzazione basata su uno è piuttosto goffo:

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

Le operazioni automatiche del modulo imposte dall'aritmetica binaria senza segno di dimensioni fisse con avvolgimento sono un altro esempio del motivo per cui ciò ha senso.

Per entrambi

Un'altra cosa da considerare è il fatto che è abbastanza facile non usare il primo elemento di un array a base zero. (Ciò non foreachvale per iterazioni di stile e costrutti di linguaggio simili che trattano l'array nel suo insieme.) Molti programmatori, incluso me stesso, potrebbero sentirsi un po 'imbarazzanti per lo spazio sprecato, ma nella maggior parte dei casi la quantità è così piccola che queste preoccupazioni sono infondati. D'altra parte, se le lingue usano l'indicizzazione basata su uno, non c'è modo di simulare un elemento all'indice zero senza molto codice. Quindi, dato che in alcune situazioni l'indicizzazione in base zero è meglio di una in base, scegliendo zero come base ovunque è l'approccio più flessibile, al contrario di quello basato ovunque, ed è anche più coerente delle posizioni di partenza configurabili.


0

I sistemi informatici utilizzano sia numeri naturali (contando da 0) sia numeri interi (contando da 1). Le persone contano le cose in numeri interi, il che le rende intuitive per gli elenchi di numerazione e molti linguaggi di programmazione ne traggono vantaggio: BASIC, COBOL, Fortran, Lua e Pascal contano tutti da 1. Quei linguaggi prendono di mira nicchie come l'elaborazione dei dati, l'analisi numerica, e insegnamento, in cui elenchi semplici e intuitivi sono un vantaggio.

Numeri interi diventano imbarazzanti quando inizi ad analizzare e manipolare la struttura dei dati, invece di elaborare tutto in ordine. Quando devi fare riferimento a sequenze in una formula o in un algoritmo, è più facile e meno soggetto a errori numerarli da 0, come fanno i matematici: uno 0 , un 1 , un n , ecc. Altrimenti, devi spesso regolarti di +1 e –1 per ottenere i dati giusti, ed è facile sbagliare, creando bug. Pertanto, i linguaggi progettati per gli informatici in genere utilizzano numeri naturali: C, Java e Lisp contano tutti da 0.

Oltre ai linguaggi di programmazione, molti sistemi informatici numerano le cose da 0 perché è ciò a cui sono abituati gli informatici. Inoltre, poiché la numerazione da 1 porta a così tanti bug insidiosi, molti di noi lo evitano al di fuori di elementi di interfaccia progettati esclusivamente per utenti finali non tecnici.


Java ... per gli informatici. LOL!
Kaz,

0

La semplice risposta è che il primo numero non è 1 ma è 0.

Spiegazione: La formula per calcolare un numero a più cifre in qualsiasi base è:

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

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

Prendiamo il sistema decimale, è quello a cui siamo più abituati.

Guardando il numero 1234, possiamo scriverlo come:

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.

Quindi, non siamo solo i computer, noi, le persone, contiamo anche da 0.


0

Un indice di array è l'offset dalla posizione di memoria di base alla posizione di memoria dell'elemento. L'elemento i è quindi Base + i. Il primo elemento si trova nella posizione Base, quindi è nella posizione 0 (Base + 0).


0

Oltre all'efficienza computazionale, c'è anche un altro aspetto del conteggio. Esistono due modi per assegnare a ciascun elemento di una sequenza un numero sequenziale:

  1. Il numero di elementi (interi) precedenti (numeri cardinali)
  2. La posizione dell'elemento (numeri ordinali)

Le età delle persone sono numeri cardinali: nel primo anno dopo la nascita di un bambino ha 0 anni, perché è vivo da zero anni interi.

Gli anni in date sono numeri ordinali: nel primo anno Anno Domini (AD), l'anno è 1 d.C. Non c'è anno 0, proprio come non c'è nulla di zeroth .

I linguaggi di programmazione (come Matlab e Mathematica) in cui l'indice di un elemento rappresenta la sua posizione nell'array iniziano a contare da 1: il primo elemento. In altre lingue (come tutti i linguaggi basati su C) l'indice di un elemento è il numero di elementi precedenti e quindi il primo elemento è 0.


Naturalmente, Matteo ha ragione solo in parte quando afferma che l'indicizzazione in base zero è più efficiente.

element(n) = address + n * element_size

L'indicizzazione su base singola può essere altrettanto efficiente a condizione che tutti gli indirizzi dell'array ne abbiano già element_sizesottratto uno . Questo può essere fatto quando l'array è allocato, nel qual caso è altrettanto veloce:

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

-1

I computer tradizionalmente calcolano i valori numerici a partire da zero. Ad esempio, le matrici nei linguaggi di programmazione basati su C iniziano dall'indice zero.

0 ... Stai confondendo diversi concetti: linguaggi di programmazione, computer e conteggio.

  1. L'uso di 2 stati (la maggior parte di essi schematicamente fa esattamente quello) significa che è possibile scegliere 2 cifre per mapparle (per dire, fare riferimento). "3" e "5" (o "F" e ",") andrebbero bene, ma poi chiederesti perché i computer contano da "3" (o da "F"). La scelta naturale è ovviamente 0 e 1.
  2. Le matrici in Pascal iniziano da 1. Quel linguaggio è un po 'più astratto di quanto lo sia il C di basso livello.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.