Mittwoch, August 24, 2011

Warum wir bei Null zu zählen anfangen

Der Titel mag zunächst verwundern, fangen doch die meisten Menschen bei Eins an wenn sie zählen. Dieser Umstand ist selbst in unserer Sprache verankert, die ein "erstens" kennt, während "nulltens" höchstens als Kunstwort durchgeht.

In den meisten Programmiersprachen sieht die Sache aber anders aus. Das erste Element eines Arrays mit n Elementen wird mit array[0] angesprochen, das letzte Element mit array[n-1]. Das irritiert viele, hat aber gute Gründe. Dijkstra hat diese vor langer Zeit in einem klaren Aufsatz, der schon allein der Handschrift wegen lesenswert ist, erläutert.

Dieser Aufsatz ist sehr schlüssig und logisch, aber er erklärt nicht, weshalb viele Menschen trotz guter Argumente Schwierigkeiten haben, das Zählen ab Null zu verinnerlichen. Mein Erklärungsansatz dafür ist, dass es (mindestens) zwei grundsätzlich verschiedene mentale Modelle von Arrays gibt. Ich will beide Modelle an Hand eines Strings, also einem Array aus Zeichen, illustrieren. Das erste sieht so aus:

Das Array ist eine Reihe von Kisten, und jede dieser Kisten hat eine Nummer. Dies ist vermutlich das Modell von Arrays, das die meisten Menschen im Kopf haben wenn sie zum ersten Mal mit dem Thema in Berührung kommen, und in der Tat wirkt es dann natürlicher, mit Eins anzufangen.

Schwierigkeiten treten - genau wie in Dijkstras Aufsatz geschildert - dann auf, wenn man über Teilsequenzen des Arrays reden will. Die erste Silbe des Namens geht von der ersten Kiste bis zur vierten, und man ist geneigt, dafür eine Notation wie array[1:4] einzuführen. Aber wie beschreibt man dann eine leere Teilsequenz? array[1:0] lautet die natürliche Antwort in diesem Modell, aber das wirkt doch ein wenig merkwürdig. Wie berechnet man die Länge einer Teilsequenz? Man muss das Ende vom Anfang subtrahieren und darf nicht vergessen, noch eins zu addieren - eine typische Fehlerquelle.

Bei beidem hilft das zweite mentale Modell eines Arrays, das ich persönlich bevorzuge:

Hier werden nicht die Einträge des Arrays nummeriert, sondern die Punkte dazwischen. Wie auf einem Meterstab oder dem Zahlenstrahl bezeichnen die Nummern nun "unendlich kleine" (genauer: 0-dimensionale) Punkte, während die Einträge des Arrays eine endliche (1-dimensionale) Größe haben.

Die erste Silbe geht nun ganz offensichtlich von 0 bis 4, die Notation array[0:4] bietet sich an. Die Länge der Silbe ist - ganz natürlich - die Differenz von Ende und Anfang, genau wie auf einem Meterstab. Und die leere Teilsequenz erhält man, indem man Anfang und Ende gleichsetzt.

Und mit diesem Modell ist es auch vollkommen intuitiv, dass man mit Null anfängt - denn wer hat schon einen Meterstab gesehen, der bei Eins beginnt?

Keine Kommentare: