Mengapa array berbasis nol adalah norma?

112

Sebuah pertanyaan yang diajukan di sini mengingatkan saya pada diskusi yang saya lakukan dengan sesama programmer. Dia berpendapat bahwa array berbasis nol harus diganti dengan array berbasis satu karena array berbasis nol adalah detail implementasi yang berasal dari cara array dan pointer dan kerja perangkat keras komputer, tetapi hal-hal semacam ini tidak boleh tercermin di tingkat yang lebih tinggi bahasa.

Sekarang saya tidak terlalu pandai berdebat sehingga saya tidak bisa benar-benar menawarkan alasan yang baik untuk tetap menggunakan array berbasis nol selain mereka merasa lebih cocok. Mengapa adalah nol titik awal umum untuk array?

Tamas Czinege
sumber
Dalam array n-elemen, elemen 'n' tidak ada. Array n-elemen memiliki anggota yang jumlahnya dari 0 hingga n-1 saja. Jadi, bukankah lebih baik jika kita memiliki array mulai dari 1 dan array n-elemen sebenarnya mewakili elemen n yang ada dalam array.
Saya suka array berbasis nol karena bit pertama dalam byte adalah 2 ^ 0, bukan 2 ^ 1. Terkadang hal ini membantu saya :)
e-MEE
Jika seseorang melihat daftar ini misalnya, en.wikipedia.org/wiki/… , orang akan melihat bahwa sebagian besar bahasa domain spesifik mulai mengindeks pada 1, dan sebagian besar bahasa dari cs school of thinking at 0. Jika seseorang mencari sedikit lebih lama , ia akan memperhatikan bahwa begitu banyak diskusi bodoh telah dilakukan mengenai hal ini, sehingga mungkin tidak ada gunanya untuk mencoba berbicara di antara keduanya untuk mengubah cara mereka. Dalam membela "1", kebanyakan orang di dunia menggunakan yang itu. Sebagian besar programmer menggunakan "0". Kebanyakan orang tidak mengerti programmer, sehingga membuat Anda berpikir ...
Rook
Saya tidak percaya pertanyaan ini dimigrasikan dari StackOverflow ke Programmer, dan kemudian ditutup sebagai tidak konstruktif. Ini bodoh.
paercebal

Jawaban:

105

Saya tidak berpikir ada di antara kita yang bisa memberikan argumen yang lebih kuat daripada artikel Edsger W. Dijkstra "Mengapa penomoran harus dimulai dari nol" .

Bill the Lizard
sumber
Dia memang memunculkan beberapa statistik dan menggunakan bukti gaya matematika. Tapi saya yakin seseorang masih bisa berdebat. Meskipun saya menyetujui jadi saya tidak akan.
6
Artikel Dijkstra adalah tentang gaya, tetapi kemudian, argumennya adalah tentang kesederhanaan dan kemudahan penggunaan ... +1.
paercebal
80

Argumen otoritas

Ya ... Rupanya, sebagian besar bahasa, termasuk yang sangat baru, berbasis nol. Karena bahasa-bahasa itu ditulis oleh orang-orang yang cukup ahli, teman Anda pasti salah ...

Mengapa satu?

mengapa 1 akan menjadi indeks awal yang lebih baik daripada nol? Kenapa tidak 2, atau 10? Jawabannya sendiri menarik karena menunjukkan banyak tentang proses berpikir orang-orang yang membela ide tersebut.

The pertama argumen adalah bahwa itu lebih alami, karena 1 biasanya satu sebelum semua orang lain, setidaknya, untuk sebagian besar orang ...

Argumen nomor satu adalah bahwa indeks terakhir juga ukuran array ...

Saya masih terkesan dengan "kualitas" alasan saya biasanya mendengar argumen semacam ini ... Dan bahkan lebih ketika saya diingatkan bahwa ...

Kenapa tidak nol?

... Notasi "berbasis satu" adalah sisa dari budaya barat yang mengabaikan keberadaan nol selama berabad-abad, jika tidak lebih.

Percaya atau tidak, kalender asli Gregorian berasal dari -3, -2, -1, 1, 2, 3 ... Coba bayangkan masalah yang dikontribusikannya pada ilmu pengetahuan barat (misalnya, berapa tahun sejak 1 Januari -2 hingga 1 Januari 2 untuk melihat daripada kalender asli kalender bertentangan dengan sesuatu yang sederhana seperti substraksi ...).

Menjaga array berbasis satu adalah seperti (well, saya akan downmodded untuk itu ... ^ _ ^ ...), menjaga mil dan yard di abad ke-21 ...

Mengapa nol Karena ini matematika!

Pertama (Ups ... Maaf ... saya akan coba lagi)

Nol , Nol bukanlah apa-apa, satu adalah sesuatu. Dan beberapa teks agama menyatakan bahwa "Pada awalnya, tidak ada apa-apa". Beberapa diskusi yang berhubungan dengan komputer bisa sama berbahayanya dengan perdebatan agama, jadi poin ini tidak terlalu keluar dari topik seperti yang terlihat ... ^ _ ^

Pertama , Lebih mudah untuk bekerja dengan array berbasis nol dan mengabaikan nilai nol-nya daripada bekerja dengan array berbasis satu dan meretas untuk menemukan nilai nol-nya. Alasan ini hampir sama bodohnya dengan yang sebelumnya, tetapi kemudian, argumen asli yang mendukung array berbasis satu juga cukup keliru.

Kedua , Mari kita ingat bahwa ketika berhadapan dengan angka-angka, kemungkinan besar Anda akan berurusan dengan matematika satu saat atau yang lain, dan ketika Anda berurusan dengan matematika, kemungkinan besar Anda tidak berminat untuk peretasan bodoh untuk menyiasati konvensi usang. Notasi berbasis satu mengganggu matematika dan tanggal selama berabad-abad juga, dan dengan belajar dari kesalahan kita, kita harus berusaha menghindarinya dalam ilmu berorientasi masa depan (termasuk bahasa komputer).

Ketiga , seperti untuk array bahasa komputer yang diikat ke perangkat keras, alokasikan array C 21 integer, dan pindahkan pointer 10 indeks ke kanan, dan Anda akan memiliki array [-10 hingga 10] yang alami. Ini tidak wajar untuk perangkat keras. Tapi ini untuk matematika. Tentu saja, matematika bisa menjadi usang, tetapi terakhir kali saya memeriksa, kebanyakan orang di dunia percaya itu tidak.

Empat , Seperti yang sudah ditunjukkan di tempat lain, bahkan untuk posisi diskrit (atau jarak direduksi menjadi nilai diskrit), indeks pertama akan menjadi nol, seperti lantai dalam bangunan (mulai dari nol), hitungan mundur yang menurun (3, 2, 1, NOL !), ketinggian tanah, piksel pertama dari suatu gambar, suhu (nol Kelvin, untuk nol mutlak, atau nol derajat celcius, sebagai suhu pembekuan air 273 K). Bahkan, satu-satunya hal yang benar-benar dimulai dengan satu adalah cara tradisional " pertama , kedua , ketiga , dll." notasi iterasi , yang membuat saya secara alami ke titik berikutnya ...

Lima yang selanjutnya titik (yang secara alami mengikuti sebelumnya ) adalah bahwa kontainer tingkat tinggi harus diakses, bukan dengan indeks, tetapi dengan iterator , kecuali indeks sendiri memiliki nilai intrinsik. Saya terkejut pengacara "bahasa tingkat tinggi" Anda tidak menyebutkan hal itu. Dalam hal indeks itu sendiri penting, Anda dapat bertaruh separuh dari waktu Anda memiliki pertanyaan terkait matematika. Dan dengan demikian, Anda ingin wadah Anda ramah-matematika, dan tidak cacat-matematika seperti "kalender gregorian lama Anda" mulai dari 1, dan membutuhkan retasan yang dimuntahkan untuk membuatnya berfungsi.

Kesimpulan

Argumen yang diberikan oleh sesama programmer Anda adalah kekeliruan karena itu tidak perlu mengikat kebiasaan bahasa lisan / tulisan, yang, pada dasarnya, buram, ke bahasa komputer (di mana Anda tidak ingin instruksi Anda kabur), dan karena dengan menghubungkan perangkat keras secara salah alasan untuk masalah ini, he.she berharap untuk meyakinkan Anda, karena bahasa semakin tinggi di abstraksi, bahwa array berbasis nol adalah sesuatu dari masa lalu.

Array berbasis nol adalah berbasis nol karena alasan terkait matematika. Bukan karena alasan terkait perangkat keras.

Sekarang, jika ini merupakan masalah bagi sesama programmer Anda, minta dia mulai memprogram dengan konstruksi tingkat tinggi yang nyata, seperti iterator dan foreach loop.

paercebal
sumber
nol derajat celcius adalah 273,15 ribu;)
2
Saya tahu (saya memiliki ijazah Master Fisika), tetapi saya merasa bermain dengan desimal kurang penting daripada sisi lucu yang saya coba untuk mewarnai argumen saya dengan ... ^ _ ^ ...
paercebal
20
Paragraf Anda diberi label "Nol, Pertama, Kedua, Ketiga, Empat, Lima". Untuk konsistensi, Anda harus menggunakan nomor kardinal ("Nol, Satu, Dua, Tiga, Empat, Lima") atau nomor urut ("Zeroth, Pertama, Kedua, Ketiga, Keempat, Kelima"). :-)
ShreevatsaR
10
Demikian pula, untuk tahun pertama kehidupan kita, kita tidak berusia satu tahun tetapi berusia nol tahun
3
@Nikita Rybak: Yang menakjubkan adalah Anda melewatkan apa yang dilihat oleh semua komentator sebelum Anda: Tentu saja jawaban Bill the Lizard adalah yang benar. Inilah mengapa saya memilihnya sebagai +1, dan inilah mengapa dipilih sebagai jawaban terbaik pertanyaan itu. Jawaban saya lebih lanjut tentang mengolok-olok alasan keliru di balik array berbasis 1, dan menawarkan kasus konkret di mana array berbasis 1 akan menjadi gangguan. Namun, saya terkejut Anda menemukan "tidak satu pun yang meyakinkan", bahkan mengingat alasan dicampur dengan ironi ...
paercebal
47

Interval setengah terbuka menghasilkan komposisi yang baik. Jika Anda berurusan 0 <= i < limdan ingin memperluas menurut nelemen, elemen baru memiliki indeks dalam rentang tersebut lim <= i < lim + n. Bekerja dengan array berbasis nol membuat aritmatika lebih mudah saat memisahkan atau menggabungkan array atau ketika menghitung elemen . Orang berharap aritmatika sederhana menyebabkan kesalahan fencepost lebih sedikit .

Norman Ramsey
sumber
+1 untuk interval setengah terbuka - itu hanya membuat segalanya lebih mudah.
Eclipse
29

Jenis manipulasi array tertentu menjadi rumit dengan array berbasis 1, tetapi tetap lebih sederhana dengan array berbasis 0.

Saya melakukan beberapa pemrograman analisis numerik pada satu titik. Saya bekerja dengan algoritma untuk memanipulasi matriks yang dikompresi, jarang, ditulis dalam FORTRAN dan C ++.

Algoritma FORTRAN memiliki banyak a[i + j + k - 2], sedangkan C ++ memiliki a[i + j + k], karena array FORTRAN berbasis 1, sedangkan array C ++ berbasis 0.

Jay Bazuzi
sumber
Saya setuju. Satu-satunya momen di mana saya menemukan array berbasis 1 berguna adalah ketika saya ingin memberikan ruang untuk indeks null-item. Sebagai contoh, jika saya memiliki array objek dan menggunakan indeks mereka sebagai pegangan, dan ingin memiliki pegangan nol.
Fabio Ceconello
Saya telah mencapai komplikasi yang tidak perlu dari 1 array berbasis juga, 0 array berdasarkan, dalam pengalaman terbatas saya, selalu menghasilkan kode yang lebih jelas untuk pengindeksan array dengan pengecualian langka.
Bagaimana indeks FORTRAN dan C ++ berbeda 2 jika indeks masing-masing hanya diimbangi oleh 1? Juga, mengapa minus 2? Jika FORTRAN berbasis 1, bukankah Anda akan menambahkan 2 (atau 1)?
RexE
@RexE: Begitulah cara kerjanya, dan itulah mengapa sangat rumit dengan array berbasis 1.
Jay Bazuzi
@RexE: Misalkan Anda meniru array 3d dengan yang datar. Kemudian, di 0 dasar, elemen (0 0 0) sesuai dengan elemen 0 dalam array datar. OTOH, jika berbasis 1, elemen (1 1 1) sesuai dengan elemen 1 dalam susunan datar: 1 + 1 + 1-2.
22

Indeks dalam array sebenarnya bukan indeks. Ini hanyalah offset yang merupakan jarak dari awal array. Elemen pertama adalah di awal array sehingga tidak ada jarak. Oleh karena itu offsetnya adalah 0.

Thomas
sumber
3
Untuk sebagian besar bahasa yang dirancang saat ini, ini benar-benar detail implementasi, yang seharusnya tidak muncul dalam bahasa (kecuali ketika ada alasan lain yang lebih baik untuk melakukannya)
Jens Schauder
17

Alasannya bukan hanya historis: C dan C ++ masih ada dan banyak digunakan dan aritmatika pointer adalah alasan yang sangat valid untuk membuat array mulai dari indeks 0.

Untuk bahasa lain yang tidak memiliki aritmatika pointer, apakah elemen pertama pada indeks 0 atau 1 lebih merupakan konvensi daripada yang lainnya.
Masalahnya adalah bahwa bahasa yang menggunakan indeks 1 sebagai elemen pertama mereka tidak ada dalam ruang hampa dan biasanya harus berinteraksi dengan perpustakaan yang sering ditulis dalam -Anda dapat menebaknya- C atau C ++ ...

VB dan rasa turunannya menderita karena memiliki array mulai dari 0 atau 1 dan sudah menjadi sumber masalah untuk waktu yang lama.

Intinya adalah: tidak masalah apa bahasa Anda menganggap indeks elemen pertama sepanjang konsisten. Masalahnya adalah bahwa menganggap 1 sebagai indeks pertama membuatnya lebih sulit untuk dikerjakan dalam praktik.

Renaud Bompuis
sumber
Sepakat. Konsistensi penting, dan kecuali Anda memiliki kemewahan untuk menghindari kode level rendah (termasuk C / C ++) sepenuhnya maka bekerja dengan array berbasis 1 hanya akan menimbulkan masalah.
Shog9
Sementara kita berada di sana, sebuah pertanyaan: apakah Anda pernah menggunakan kode tingkat rendah dengan cara khusus non-platform? Dengan kata lain, Anda selalu berada di satu platform atau yang lain dan Anda harus tahu yang mana, kan?
Dan Rosenstark
1
Sebagai seseorang yang berpikir VB. NET biasanya difitnah secara tidak adil, saya harus mengatakan bahwa praktek VB. NET pada array mengerikan. Mereka membagi perbedaan dan membuatnya lebih membingungkan: Array mulai dari 0, tetapi Dim a sebagai Integer (5) menciptakan sebuah array dengan 6 posisi. Alasannya tampaknya memiliki posisi ekstra lebih baik daripada memiliki bug dari mengatasi panjang array. Sayangnya pada hal itu (dan masalah lainnya, seperti Dan dan Atau menjadi bitwise) mereka tertekan oleh tuntutan banyak programmer VB6 yang akhirnya tidak menggunakan VB. NET.
Kyralessa
1
@ Kirralessa: Tidak, alasannya adalah untuk memiliki kompatibilitas ke belakang ke VB6 (asisten pemutakhiran otomatis ...) meskipun mereka sangat menyadari bahwa notasi tersebut kontra-intuitif dan rawan kesalahan. Di sisi lain, Anddan Ormenjadi bitwise tidak ada hubungannya dengan VB6, itu satu-satunya solusi logis untuk bahasa tipe-VB. Anda tidak memiliki AndAlsodan OrElseuntuk operasi logis Anda.
Konrad Rudolph
Anddan Ormenjadi bitwise ada hubungannya dengan VB6, karena mereka bitwise di VB6. Operator yang jelek AndAlsodan OrElseseharusnya dibuat bitwise, karena operasi bitwise jauh lebih jarang daripada yang logis. Ada banyak kutil jelek seperti yang tertinggal pada bahasa karena "kompatibilitas mundur", seperti fakta bahwa ByVal terpampang di semua tempat meskipun itu default.
Kyralessa
10

Array berbasis nol berakar pada C dan bahkan assembler. Dengan C, pointer matematika pada dasarnya berfungsi seperti ini:

  • Setiap elemen array menempati sejumlah byte. Bilangan bulat 32 bit adalah (jelas) 4 byte;
  • Alamat sebuah array ditempati oleh elemen pertama dari array dengan elemen-elemen berikutnya dalam blok-blok yang berukuran sama setelahnya.

Sebagai ilustrasi, anggap int a[4]pada 0xFF00, alamatnya adalah:

  • a [0] -> 0xFF00;
  • a [1] -> 0xFF04;
  • a [2] -> 0xFF08;
  • a [3] -> 0xFF0C.

Jadi, dengan indeks berbasis nol, matematika addres sederhana:

Alamat elemen = Alamat array + indeks * sizeof (tipe)

Bahkan ekspresi dalam C semuanya sama:

  • a [2];
  • 2 [a]; dan
  • * (a + 2).

Dengan array berbasis satu, perhitungan matematika menjadi sedikit lebih rumit.

Jadi alasannya sebagian besar historis.

cletus
sumber
1
Pertanyaan aslinya sudah menyatakan "array yang berbasis nol adalah detail implementasi yang berasal dari cara array dan pointer dan perangkat keras komputer bekerja, tetapi hal-hal semacam ini tidak boleh tercermin dalam bahasa tingkat yang lebih tinggi."
Layak disebutkan bahwa bahasa yang memungkinkan array berbasis N biasanya menghasilkan kode dengan 'offset' array secara otomatis dihitung dengan biaya runtime nol.
Roddy
8

Jika Anda menggunakan array berbasis nol, panjang array adalah himpunan indeks yang valid. Setidaknya, itulah yang dikatakan aritmetika Peano:

0 = {}
1 = 0 U {0} = {0}
2 = 1 U {1} = {0,1}
3 = 2 U {2} = {0,1,2}
...
n = n-1 U {n-1} = {0,1,2...n-1}

Jadi ini adalah notasi yang paling alami.

ular sanca
sumber
7

Karena ada korelasi yang kuat antara array dan pointer di C

char* p = "hello";
char q[] = "hello";

assert(p[1] == q[1]);

assert(*p == *q)

* p sama dengan * (p + 0)

memiliki indeks awal 1 akan memberi Anda sakit kepala nanti

Anders
sumber
5

Tumpukan adalah salah satu contoh kelebihan array berbasis 1. Diberi indeks i , indeks orang tua i dan anak kiri adalah

PARENT[ i ] = i ÷ 2

LCHILD[ i ] = i × 2

Tetapi hanya untuk array berbasis 1. Untuk array berbasis 0 yang Anda miliki

PARENT[ i ] = ( i + 1) ÷ 2 - 1

LCHILD[ i ] = ( i + 1) × 2 - 1

Dan kemudian Anda memiliki properti yang saya juga ukuran sub-array untuk indeks itu (yaitu indeks dalam kisaran [1, i ]).

Tetapi pada akhirnya itu tidak masalah, karena Anda dapat membuat array berbasis 0 menjadi array berbasis 1 dengan mengalokasikan satu elemen lebih banyak dari biasanya, dan mengabaikan zeroth. Dengan demikian Anda dapat memilih ikut serta untuk mendapatkan manfaat dari array berbasis 1 saat yang tepat, dan menyimpan array berbasis 0 untuk aritmatika bersih di hampir semua situasi lain.

sgm
sumber
4

Perasaan saya adalah bahwa itu sepenuhnya sewenang-wenang. Tidak ada yang istimewa dari array berbasis nol atau satu. Sejak membebaskan diri dari Visual Basic (kebanyakan, kadang-kadang saya melakukan hal-hal kecil di Excel) saya belum pernah bekerja dengan array berbasis 1, dan ... itu sama. Faktanya adalah bahwa jika Anda memerlukan elemen ketiga array, itu hanya detail implementasi yang disebut 3 atau 2. Namun, 99% pekerjaan yang Anda lakukan dengan array hanya tertarik pada dua titik absolut: elemen pertama dan hitungan atau panjangnya. Sekali lagi, itu hanya detail implementasi bahwa elemen pertama disebut nol bukan satu, atau bahwa elemen terakhir disebut count-1 atau, sebaliknya, menghitung.

Sunting: Beberapa penjawab telah menyebutkan bahwa array berbasis 1 lebih rentan terhadap kesalahan fencepost. Dalam pengalaman saya, memikirkannya sekarang, ini benar. Saya ingat berpikir, dalam VB, "ini akan berhasil atau akan meledak karena saya pergi satu per satu." Di Jawa itu tidak pernah terjadi. Meskipun saya pikir saya menjadi lebih baik, beberapa penjawab menunjukkan kasus-kasus di mana array berbasis 0 menghasilkan aritmatika yang lebih baik, BAHKAN ketika Anda tidak harus berurusan dengan bahasa tingkat yang lebih rendah.

Dan Rosenstark
sumber
Di PHP, sebagian besar pencarian di dalam fungsi string mengembalikan FALSE pada tidak ditemukan. Bukan -1.
jmucchiello
Anda mengacaukan hitungan dengan indeks elemen terakhir. Hitungan array kosong selalu 0, apakah Anda menggunakan array berbasis nol atau satu. Keuntungan dari array berbasis satu adalah bahwa penghitungan adalah posisi elemen terakhir (tapi itu satu-satunya keuntungan).
Benar mengenai kedua poin ini: setengah terakhir dihapus, karena sama untuk array berbasis-nol atau berbasis-satu: jumlah adalah 0 jika Anda memiliki elemen nol.
Dan Rosenstark
Maksud saya bagian terakhir dari jawaban saya ...
Dan Rosenstark
4

Sebagai programmer 10 + tahun C / C ++, dengan latar belakang yang sangat kuat di Pascal dan Delphi, saya masih merindukan pengecekan array array dan index type yang kuat dari Pascal, serta fleksibilitas dan keamanan yang menyertainya. Contoh nyata dari ini adalah data array yang menyimpan nilai untuk setiap bulan.

Pascal:

 Type Month = (Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec);

  Var Days[Month] of integer;

  ... 
  if Year mod 4 = 0 then // yes this is vastly simplified for leap years and yes i don't know what the comment marker is in pascal and no i won't go look it up
    Days[Feb] := 29
  else
    Days[Feb] := 28;

Menulis kode serupa dalam bahasa C tanpa menggunakan +/- 1 atau 'angka ajaib' cukup menantang. Perhatikan bahwa ekspresi seperti Days [2] dan Days [Jan + Dec] tidak akan dikompilasi, yang dapat tampak brutal bagi orang yang masih berpikir dalam C atau Assembler.

Saya harus mengatakan ada banyak aspek dari bahasa Pascal / Delphi yang tidak saya lewatkan sedikit pun, tetapi array berbasis nol C tampaknya hanya "bodoh" dengan perbandingan.

Roddy
sumber
Mungkin perlu dicatat bahwa algoritme Anda tidak benar untuk tahun 2100. en.wikipedia.org/wiki/Leap_year#Algorithm
2
Saya tahu ;-) Namun, itu benar untuk tahun 2000. Saya hanya bermain "lihat pedant" ...
Roddy
Temukan pedant! LOL.
jcollum
Iya. Hindari seluruh masalah, basiskan array sesuai keinginan Anda.
Loren Pechtel
Saya tidak akan terkejut jika rata-rata compiler Pascal Anda memberikan Jan = 0, Desember = 11 saat membuat kode mesin :-)
4

Alasannya dimulai pada 0 dan bukan 1 adalah Anda dapat menganggap offset sebagai seberapa jauh dari awal memori array adalah elemen ini. Itu tidak mengatakan memberi saya elemen 0 - itu mengatakan, beri saya elemen yang merupakan 0 elemen sejak awal.

Cara lain untuk melihatnya adalah bahwa ini (sebagian besar) adalah setara:

array[n]

*(array + n)

Alasan standar tidak akan pernah berubah adalah karena C telah ada selama sekitar 40 tahun sekarang. Tidak ada alasan kuat untuk mengubahnya dan jika mereka melakukannya, semua kode yang ada yang tergantung pada awal array yang berada pada 0 akan rusak.

Dennis Munsie
sumber
Bahkan, Anda dapat menulis ulang array[n]seperti n[array]pada C. Ini bukan ide yang baik untuk melakukannya, itu membingungkan! Tapi itu legal (well, setidaknya hingga C89) karena identitas itu di atas dan fakta bahwa penambahan itu komutatif.
Donal Fellows
Itu adalah cara yang gila untuk menulis itu - sesuatu yang jika Anda melihat kode apa pun yang harus Anda pertahankan akan menjadi tanda peringatan besar. Untungnya saya belum menemukan itu ... belum :)
Dennis Munsie
4

Kode termasuk beberapa informasi posisi awal / posisi relatif jauh lebih bersih dengan array mulai dari 0.

Sebagai contoh: Kode untuk menyalin vektor pada posisi yang ditentukan dalam vektor yang lebih besar adalah rasa sakit dengan array mulai dari 1:

function copyAtPos (dest, vect, i):
    for i from 1 -> vect.length do
        dest[pos+i-1] = vect[i]

Dengan oposisi dengan array mulai dari 0:

function copyAtPos (dest, vect, i):
    for i from 0 -> vect.length-1 do
        dest[pos+i] = vect[i]

Jika Anda mulai menulis formula konvolusi besar, itu menjadi keharusan.

poulejapon
sumber
3

Kenapa tidak 2 atau 3 atau 20? Ini tidak seperti memiliki array berbasis 1 entah bagaimana lebih mudah atau lebih sederhana untuk memahami kemudian array berbasis nol. Untuk beralih ke array berbasis 1, setiap programmer di luar sana harus mempelajari kembali cara bekerja dengan array.

Dan selanjutnya, ketika Anda berurusan dengan offset ke array yang ada, itu lebih masuk akal juga. Jika Anda telah membaca 115 byte dari sebuah array, Anda tahu potongan berikutnya dimulai pada 115. Dan seterusnya, byte berikutnya selalu ukuran byte yang Anda baca. Dengan berbasis 1, Anda harus menambahkannya setiap saat.

Dan Anda kadang-kadang perlu berurusan dengan potongan data dalam array, bahkan dalam bahasa tanpa aritmatika pointer "benar". Di java Anda bisa memiliki data dalam file yang dipetakan dalam memori, atau buffer. Dalam hal ini, Anda tahu blok i pada ukuran * i. Dengan indeks berbasis 1 akan berada di blok * i + 1.

Dengan pengindeksan berbasis 1, banyak teknik akan membutuhkan +1 di semua tempat.

Chad Okere
sumber
Kenapa tidak 2 atau 3 atau 20? Karena 0 adalah identitas aditif dan 1 adalah identitas multiplikatif. Mereka paling masuk akal.
3

Menggunakan array berbasis 1, ubah array satu dimensi menjadi array multi dimensi:

int w = 5, h = 5, d = 5;

int[] a1 = new int[w * h * d], new a2 = int[w,h,d];

for (int z = 1; z <= d; z++)

  for (int y = 1; y <= h; y++)

    for (int x = 1; x <= w; x++)

      a1[x + (y - 1) * w + (z - 1) * h] = a2[x,y,z];

Perhatikan bahwa indeks y dan z Anda berbasis 0 (y - 1, z - 1) bahkan ketika array Anda berbasis 1. Dalam beberapa keadaan, Anda tidak dapat menghindari indeks berbasis 0. Untuk konsistensi, mengapa tidak selalu menggunakan indeks berbasis 0?

enjerth
sumber
3

Mengapa Anda ingin array dimulai pada satu?

Ketika Anda mengatakan a[x][y], compiler menerjemahkan ini ke: a+(x*num_cols+y). Jika array dimulai pada satu, ini akan menjadi a+(x*num_cols+y-1). Ini akan menjadi operasi aritmatika tambahan setiap kali Anda ingin mengakses elemen array. Mengapa Anda ingin memperlambat program?

Borealid
sumber
1
sebenarnya, itu harus menjadi + ((x - 1) * num_cols) + y - 1) - baik x dan y akan mulai dari 1.
Dennis Munsie
2

Saya akan melangkah mengambil risiko di sini dan menyarankan sesuatu yang berbeda dari array 'kunci' integer.

Saya pikir rekan kerja Anda mulai membuat pemetaan satu-ke-satu dari 'set' di dunia fisik di mana kita selalu mulai menghitung pada 1. Saya bisa mengerti ini, ketika Anda tidak melakukan sesuatu yang mewah, mudah untuk memahami beberapa kode ketika Anda dipetakan 1 ke 1 antara perangkat lunak dan dunia fisik.

Saran saya

Jangan gunakan array berbasis integer untuk apa pun yang Anda simpan, tetapi gunakan beberapa jenis kamus atau pasangan nilai kunci lainnya. Peta ini lebih baik untuk kehidupan nyata karena Anda tidak terikat oleh integer yang berubah-ubah. Ini memiliki tempatnya dan saya akan merekomendasikan menggunakannya sebanyak mungkin karena manfaat dari konsep pemetaan 1 hingga 1 antara perangkat lunak dan dunia fisik.

yaitu kvp['Name Server'] = "ns1.example.com"; (Ini hanya satu dari sejuta contoh yang mungkin).

Discaimer

Ini pasti tidak berfungsi ketika Anda bekerja dengan konsep yang berbasis di matematika, pada dasarnya karena matematika lebih dekat dengan implementasi aktual dari komputer. Menggunakan set kvp tidak akan membantu apapun di sini, tetapi sebenarnya akan mengacaukan segalanya dan membuatnya lebih bermasalah. Saya belum memikirkan semua kasus sudut di mana sesuatu dapat bekerja lebih baik sebagai kvp atau sebagai array.

Gagasan akhirnya adalah menggunakan array berbasis nol atau pasangan nilai kunci yang masuk akal, ingatlah bahwa ketika Anda hanya memiliki palu, setiap masalah mulai terlihat seperti paku ...

Bryan Rehbein
sumber
2

Secara pribadi, satu argumen adalah ketika melihat indeks array sebagai offset. Masuk akal.

Orang bisa mengatakan bahwa ini adalah elemen pertama, tetapi offset elemen pertama relatif terhadap asal array adalah nol. Dengan demikian, mengambil asal array dan menambahkan nol akan menghasilkan elemen pertama.

Jadi dalam komputasi lebih mudah untuk menambahkan nol untuk menemukan elemen pertama daripada menambahkan satu dan kemudian menghapusnya.

Saya pikir siapa pun yang melakukan hal-hal tingkat rendah selalu berpikir basis nol jalan. Dan orang-orang yang mulai atau terbiasa ke tingkat yang lebih tinggi sering tidak pemrograman algoritmik mungkin menginginkan sistem basis satu. Atau mungkin kita hanya bias oleh pengalaman masa lalu.

Loki
sumber
Tepat - itu pada dasarnya adalah konvensi yang terletak di sekitar bahasa tingkat bawah.
2

Hanya dua (sangat) alasan serius untuk menggunakan indeks berbasis 0 dan bukan indeks berbasis 1 tampaknya untuk menghindari mendidik kembali banyak programmer DAN untuk kompatibilitas mundur .

Saya tidak melihat argumen serius lainnya terhadap indeks berbasis 1 di semua jawaban yang Anda terima.

Bahkan, indeks secara alami berbasis 1 , dan inilah sebabnya.

Pertama, kita harus bertanya: Dari mana array berasal? Apakah mereka memiliki padanan dunia nyata? Jawabannya adalah ya: mereka adalah bagaimana kita memodelkan vektor dan matriks dalam ilmu komputer. Namun, Vektor dan matriks adalah konsep matematika yang menggunakan indeks berbasis 1 sebelum era komputer (dan yang sebagian besar masih menggunakan indeks berbasis 1 saat ini).

Di dunia nyata, indeks adalah 1-pangkalan.

Seperti yang dikatakan Thomas di atas, bahasa yang menggunakan indeks 0-base sebenarnya menggunakan offset , bukan indeks. Dan pengembang yang menggunakan bahasa ini memikirkan offset , bukan indeks. Ini tidak akan menjadi masalah jika semuanya dinyatakan dengan jelas, tetapi tidak. Banyak pengembang yang menggunakan offset masih berbicara tentang indeks. Dan banyak pengembang yang menggunakan indeks masih tidak tahu bahwa C, C ++, C #, ... menggunakan offset.

Ini adalah masalah kata - kata .

(Catatan tentang makalah Diskstra - Dikatakan persis apa yang saya katakan di atas : ahli matematika memang menggunakan indeks berbasis 1. Tapi Diskstra berpikir bahwa matematikawan tidak boleh menggunakannya karena beberapa ungkapan kemudian akan jelek (mis .: 1 <= n <= 0 Yah, tidak yakin dia benar tentang hal itu - melakukan perubahan paradigma sedemikian rupa untuk menghindari urutan kosong yang luar biasa itu tampaknya banyak masalah untuk hasil yang sedikit ...)

Sylvain
sumber
2
Matematikawan tidak selalu menggunakan indeks berbasis 1. Saya telah melihat x0 digunakan banyak kali untuk nilai awal dari suatu urutan. Itu tergantung mana yang lebih nyaman.
2

Pernahkah Anda terganggu oleh "abad ke-20" yang sebenarnya mengacu pada tahun 1900-an? Yah, itu analogi yang baik untuk hal-hal yang membosankan yang Anda hadapi setiap saat ketika menggunakan array berbasis 1.

Pertimbangkan tugas array umum seperti metode baca .net IO.stream:

int Read(byte[] buffer, int offset, int length)

Inilah yang saya sarankan agar Anda meyakinkan diri sendiri bahwa array berbasis 0 lebih baik:

Di setiap gaya pengindeksan, tulis kelas BufferedStream yang mendukung membaca. Anda dapat mengubah definisi fungsi Baca (mis. Gunakan batas bawah alih-alih offset) untuk array berbasis 1. Tidak perlu sesuatu yang mewah, hanya membuatnya sederhana.

Sekarang, yang mana dari implementasi itu yang lebih sederhana? Yang mana yang memiliki offset +1 dan -1 disebarkan di sana-sini? Itulah yang saya pikir. Sebenarnya saya berpendapat bahwa satu-satunya kasus di mana gaya pengindeksan tidak penting adalah ketika Anda seharusnya menggunakan sesuatu yang bukan array, seperti Set.

Craig Gidney
sumber
Ini analogi yang buruk membingungkan logika integer dengan floating point.
2

Itu karena bagaimana array dibangun. Tidak masuk akal bagi mereka untuk memulai dari satu. Array adalah alamat dasar dalam memori, ukuran, dan indeks. Untuk mengakses elemen ke-n, itu:

base + n * element_size

Jadi 0 jelas merupakan offset pertama.

Gian
sumber
1

Sebenarnya ada beberapa cara berbeda untuk mengimplementasikan ini:

  • Indeks array berbasis 0
  • Indeks array berbasis 1
  • baik array berbasis 0 atau 1 (seperti VB 6.0 ... ini benar-benar mengerikan)

Pada akhirnya, saya rasa tidak masalah apakah suatu bahasa menggunakan 0 atau 1 array berdasarkan. Tapi, saya pikir pilihan terbaik adalah menggunakan array berbasis 0, karena alasan sederhana bahwa kebanyakan programmer terbiasa dengan konvensi itu, dan itu konsisten dengan sebagian besar kode yang sudah ditulis.

Satu-satunya cara Anda benar-benar bisa salah, adalah tidak konsisten seperti Visual Basic. Basis kode yang saat ini saya pertahankan dibagi antara 0 dan 1 array berdasarkan; dan sangat sulit untuk mencari tahu mana yang mana. Ini mengarah ke verbose yang mengganggu untuk perulangan:

dim i as integer, lb as integer, ub as integer
lb = LBound(array)
ub = UBound(array)
for i = lb to ub
       '...
next
Colin
sumber
hahaha Saya ingat itu, pria yang mengisap ...
Dan Rosenstark
Saya pikir saya ingat bahkan memiliki array yang dimulai dengan angka negatif. Hanya satu dari banyak alasan saya menjauh dari VB.
1

Nol adalah wajar ketika berbicara tentang lokasi item dalam koleksi linier.

Pikirkan rak penuh buku - buku pertama terletak rata dengan dinding sisi rak - itu lokasi nol.

Jadi saya kira itu tergantung pada apakah Anda mempertimbangkan indeks array alat untuk menemukan sesuatu atau merujuk pada sesuatu.

f100
sumber
1

Saya lebih suka 0 berdasarkan indeks sejak sejak modulo (dan operator AND ketika digunakan untuk modulo) selalu mengembalikan 0 untuk beberapa nilai.

Saya sering menemukan diri saya menggunakan array seperti ini:

int blah = array[i & 0xff];

Saya sering mendapatkan kode yang salah ketika menggunakan 1 indeks berbasis.

Laserallan
sumber
1

Sulit untuk mempertahankan 0-base tanpa memprogram banyak kode berbasis array, seperti pencarian string dan berbagai algoritma sorting / penggabungan, atau mensimulasikan array multi dimensi dalam array dimensi tunggal. Fortran berbasis 1, dan Anda membutuhkan banyak kopi untuk menyelesaikan kode jenis ini.

Tapi itu jauh melampaui itu. Merupakan kebiasaan mental yang sangat berguna untuk dapat memikirkan panjangnya sesuatu daripada indeks unsur-unsurnya. Misalnya, dalam melakukan grafis berbasis piksel, jauh lebih jelas untuk menganggap koordinat sebagai jatuh di antara piksel daripada pada mereka. Dengan begitu, kotak 3x3 berisi 9 piksel, bukan 16.

Contoh yang sedikit lebih jauh adalah gagasan melihat-depan dalam penguraian, atau dalam mencetak sub-total dalam sebuah tabel. Pendekatan "akal sehat" mengatakan 1) mendapatkan karakter berikutnya, token, atau baris tabel, dan 2) memutuskan apa yang harus dilakukan dengannya. Pendekatan lihat-depan mengatakan 1) menganggap Anda dapat melihatnya, dan memutuskan apakah Anda menginginkannya, dan 2) jika Anda menginginkannya, "terima" itu (yang memungkinkan Anda melihat yang berikutnya). Kemudian jika Anda menulis pseudo-code, itu jauh lebih sederhana.

Contoh lain adalah bagaimana menggunakan "goto" dalam bahasa di mana Anda tidak punya pilihan, seperti file batch MS-DOS. Pendekatan "akal sehat" adalah untuk melampirkan label ke blok kode yang harus dilakukan, dan label mereka seperti itu. Seringkali pendekatan yang lebih baik adalah menempatkan label di ujung blok kode, untuk tujuan melompati mereka. Ini membuatnya "terstruktur" dan lebih mudah untuk dimodifikasi.

Mike Dunlavey
sumber
1

Hanya begitu, dan sudah bertahun-tahun. Mengubahnya, atau bahkan memperdebatkannya, sama bergunanya dengan mengubah atau memperdebatkan lampu lalu lintas. Mari kita buat biru = berhenti, merah = pergi.

Lihatlah perubahan yang dibuat dari waktu ke waktu dalam Numerical Recipes untuk C ++. Mereka telah menggunakan makro untuk memalsukan indeks berbasis 1, tetapi pada edisi 2001 menyerah dan bergabung dengan kawanan. Mungkin ada bahan yang mencerahkan tentang alasan di balik ini di situs mereka www.nr.com

BTW, juga menjengkelkan adalah varian menentukan rentang dari array. Contoh: python vs. IDL; a [100: 200] vs a [100: 199] untuk mendapatkan 100 elemen. Hanya harus belajar kebiasaan masing-masing bahasa. Untuk mengubah bahasa yang melakukan salah satu cara untuk mencocokkan yang lain akan menyebabkan kutukan dan kertakan gigi seperti itu, dan tidak memecahkan masalah nyata.

DarW
sumber
1

Saya lebih suka array berbasis 0 karena, seperti yang disebutkan oleh orang lain, itu membuat matematika lebih mudah. Misalnya, jika kita memiliki larik 1 dimensi dari 100 elemen yang meniru kisi 10x10, lalu apa indeks larik dari elemen di baris r, col c:

Berbasis 0: i = 10 * r + c
Berbasis 1: i = 10 * (r - 1) + c

Dan, mengingat indeks i, kembali ke baris dan kolom adalah:

Berbasis 0: c = i% 10
         r = lantai (i / 10)
Berbasis 1: c = (i - 1)% 10 + 1
         r = ceil (i / 10)

Mengingat bahwa matematika di atas jelas lebih kompleks ketika menggunakan array berbasis 1, tampaknya logis untuk memilih array berbasis 0 sebagai standar.

Namun, saya berpikir bahwa seseorang dapat mengklaim bahwa logika saya cacat karena saya berasumsi bahwa akan ada alasan untuk mewakili data 2D dalam array 1D. Saya telah mengalami sejumlah situasi seperti itu di C / C ++, tetapi saya harus mengakui bahwa perlu melakukan perhitungan seperti itu agak tergantung pada bahasa. Jika array benar-benar melakukan semua matematika indeks untuk klien, setiap saat, maka kompiler dapat dengan mudah mengubah akses array berbasis M Anda menjadi berbasis 0 pada waktu kompilasi dan menyembunyikan semua detail implementasi ini dari pengguna. Bahkan, setiap konstanta waktu kompilasi dapat digunakan untuk melakukan serangkaian operasi yang sama, meskipun konstruksi seperti itu mungkin hanya akan mengarah pada kode yang tidak dapat dipahami.

Mungkin argumen yang lebih baik adalah bahwa meminimalkan jumlah operasi indeks array dalam bahasa dengan array berbasis 1 akan mengharuskan pembagian integer dilakukan menggunakan fungsi plafon. Namun, dari perspektif matematika, pembagian integer harus mengembalikan d sisa r, di mana d dan r keduanya positif. Oleh karena itu, array berbasis 0 harus digunakan untuk menyederhanakan matematika.

Misalnya, jika Anda membuat tabel pencarian dengan elemen N, indeks terdekat sebelum nilai saat ini ke dalam array untuk nilai x adalah (kira-kira, mengabaikan nilai di mana hasilnya adalah bilangan bulat sebelum pembulatan):

Berbasis 0 dengan lantai: lantai ((N - 1) * x / xRange)
Berbasis 1 dengan lantai: lantai ((N - 1) * x / xRange) + 1
1 berbasis dengan ceil: ceil ((N - 1) * x / xRange)

Perhatikan bahwa jika konvensi standar pembulatan digunakan, array berbasis 1 memerlukan operasi tambahan, yang tidak diinginkan. Jenis matematika ini tidak dapat disembunyikan oleh kompiler, karena membutuhkan pengetahuan tingkat rendah tentang apa yang terjadi di balik layar.

Jeff G
sumber
Itu alasan yang bagus sampai Anda memiliki bahasa tingkat yang lebih tinggi yang mendukung array multi-dimensi.
1

Saya yakin programmer hanya kesal dengan kontra-intuitif dari array berbasis 0 dalam pemikiran sehari-hari dan sedang memperdebatkan cara yang lebih intuitif untuk menggambarkan array. Saya merasa ironis bahwa sebagai manusia, kita menghabiskan begitu banyak waktu untuk membuat "kelas" sehingga kita dapat mendeskripsikan hal-hal dengan cara yang lebih manusiawi dalam kode kita, tetapi ketika melihat array 0 vs 1, kita sepertinya menutup telepon Logikanya saja.

Sejauh menyangkut komputer dan secara matematis 0 mungkin akan lebih baik, tapi saya merasa ada satu titik yang terlewatkan di sini. Jika kita ingin menggambarkan sesuatu dengan cara yang lebih manusiawi (misalnya kelas), mengapa kita tidak menginginkan hal yang sama untuk bagian lain dari bahasa? Apakah itu tidak sama logis atau valid (atau mengambil prioritas yang lebih tinggi dalam hal ini ...) untuk membuat bahasa lebih mudah dimengerti dan dapat digunakan oleh manusia dan dengan demikian, dengan ekstensi, kurang rentan terhadap skenario yang cenderung membuat bug logika dan lebih cenderung untuk produksi yang lebih cepat dari kreasi yang dapat digunakan. Contoh PHP:

array(1 => 'January', 'February', 'March');

memberikan 1 array berdasarkan per permintaan kami.

Mengapa tidak memiliki norma:

array('January', 'February', 'March');

Dan pengecualiannya adalah:

array(0 => 'Value for scenario where 0 *has* to be used as the key',
      'value2', 'value3');

Dalam kasus katakanlah PHP, taruhan saya adalah 80% dari waktu array berbasis 1 menjadi sintaks default akan mengurangi bug-bug dalam kasus penggunaan dunia nyata, atau setidaknya tidak menyebabkan lebih banyak rata-rata, sementara membuatnya banyak lebih mudah pada pembuat kode untuk menghasilkan kode yang dapat digunakan lebih cepat. Ingat, saya berasumsi masih akan ada opsi, array (0 => 'value') untuk saat dibutuhkan, tetapi juga mengasumsikan sebagian besar waktu praktis untuk memiliki sesuatu yang lebih dekat dengan deskripsi dunia nyata.

Ini terdengar tidak terlalu jauh dari permintaan ketika melihatnya dari sudut pandang itu. Ketika mendekati sebuah antarmuka, baik itu OS atau bahasa untuk seorang programmer, semakin dekat dengan pemikiran manusia dan kebiasaan kita mendesainnya, semakin bahagia dalam kebanyakan kasus kita akan dan semakin sedikit kesalahpahaman antara manusia dan komputer (human logic- bug), dan produksi lebih cepat, dll. kita akan miliki. Jika 80% waktu di dunia nyata saya gambarkan dengan angka 1 saat membuat daftar atau menghitung, maka komputer idealnya harus menafsirkan makna saya menjadi cara yang dimengerti dengan informasi sesedikit atau berubah dari cara normal saya menggambarkan sesuatu mungkin. Singkatnya, semakin dekat kita dapat memodelkan dunia nyata, semakin baik kualitas abstraksinya. Jadi apa yang dia inginkan sama sekali tidak bodoh karena itu adalah tujuan akhir dan akan menjadi bukti perlunya lebih banyak abstraksi. Komputer pada akhirnya masih dapat melihatnya sebagai penggunaan khusus dari array berbasis 0. Saya tidak peduli bagaimana komputer mengartikannya selama itu adalah cara yang lebih sederhana dan lebih intuitif bagi saya untuk menggambarkan apa yang saya inginkan dengan bug yang lebih sedikit dari waktu ke waktu.

Jadi, itulah dua sen saya. Saya sangat meragukan apa yang dia katakan, atau apa yang ditafsirkan, adalah apa yang dia maksudkan. Apa yang mungkin dia maksudkan adalah, "Aku benci memiliki cara yang kurang intuitif untuk mengatakan pada komputer apa yang aku inginkan." :) Bukankah kita semua? lol.

Brian Chandler
sumber
1

Mungkin saja jika Anda berhati-hati saat menulis kode "sendiri". Anda dapat mengasumsikan indeks Anda dimulai dari n untuk semua n> = 0 dan program sesuai.

Mengenai standar, Borealid memiliki argumen yang bagus.

Praveen S
sumber