ทำไมค่าดัชชนีของอาเรย์ควรเริ่มต้นที่ 0 — Why index of array should start at zero
ทำไมอาเรย์ตัวแรกลำดับป็น 0 แทนที่จะเป็น 1 ละ?
— อาเรย์คืออะไร ?
“ Array is a data structure consisting of a collection of elements (values or variables), each identified by at least one array index or key. ”
ในทางวิทยาการคอมพิวเตอร์ อาเรย์(Array) คือ โครงสร้างข้อมูลที่เป็นรายการอย่างหนึ่ง และเป็นพอยเตอร์อย่างหนึ่งที่อ้างอิงถึงตำแหน่งของหน่วยความจำคอมพิวเตอร์ สามารถเข้าถึงข้อมูลและระบุตำแหน่งได้ด้วย ดีชชนี(Index)
แต่การที่ดัชนี(Index)ควรเริ่มที่ 0 ไม่ได้เกี่ยวกับคอนเซ็ปของวิทยาการคอมพิวเตอร์เลย แต่เป็นเรื่องของการออกแบบของภาษามากกว่า
(language design)
หมายความว่า array[n] อ้างอิงถึงตำแหน่งของหน่วยความจำ n ตัว โดยเริ่มต้นจากตัวแรก ซึ่งหมายความว่าดัชนีนั้นถูกใช้เป็น offset (ระยะห่างระหว่างจุดเริ่มต้นถึงจุดที่กำหนด)
“ Offset is an integer indicating the distance (displacement) between the beginning of the object and a given element or point ”
— ทำไมถึงดัชนีอาเรย์ควรเริ่มที่ 0 ?
แน่นอนว่า ข้อมูลตัวแรกของอาเรย์ถูกจัดเก็บไว้ที่ตำแหน่งของหน่วยความจำที่อาเรย์นั้นอ้างถึง (0 ตัว), ดังนั้นมันจึงควรแสดงเป็น array[0] นั้นเอง.
ตัวอย่าง.
อาเรย์ที่มีข้อมูล 10 ตัว จะมีดัชนีตั้งแต่ 0 ถึง 9 สมมุติให้ข้อมูลแต่ละตัวใช้หน่วยความจำ 4 ไบต์
และแถวลำดับอาเรย์นี้มีที่อยู่ในหน่วยความจำคือ 2000
จะได้ว่าที่อยู่หน่วยความจำของข้อมูลตัวที่ i คือ 2000 + 4i
หมายความว่า
ตัวที่ 1 หรือ ดัชนีที่ 0 จะอยู่ที่ : 2000 + 4(0) = 2000
ตัวที่ 2 หรือ ดัชนีที่ 1 จะอยู่ที่ : 2000 + 4(1) = 2001
ตัวที่ 3 หรือ ดัชนีที่ 2 จะอยู่ที่ : 2000 + 4(2) = 2002
.
.
.
ไปเรื่อยๆจนถึงตัวสุดท้ายซึ่ง i ก็คือ ความยาวของอาเรย์ลบด้วย 1
ในที่นี้คือ 10 – 1 = 9
นั้นเอง
— แล้วถ้าค่าเริ่มที่ 1 ละ ?
จากตัวอย่างข้างบนแทนที่ตัวแรก,ดัชนีที่ 0 จะดำเนินการแบบ : 2000 + 4(0)
คอมไพเลอร์จะสร้างใหม่เป็น 2000 + 4(0) -1
และ “-1”
อาจจะทำร้ายประสิทธิภาพของโปรแกรมได้ แทนที่จะให้โปรแกรมคำนวณ -1 ด้วยเราควรจะใช้ตำแหน่งของ array -1
เป็นหลัก เพราะว่า แม้เพียงแค่ “-1”
ก็ตามแต่จะถูกคอมไพเลอร์คำนวณสร้างหลายพันโปรแกรมและแต่ละครั้งอาจใช้คำนวณหลายพันรอบ ซึ่งอาจทำให้เกิดวงจรที่สิ้นเปลือง(wasted cycles) จากการคำนวณที่สิ้นเปลืองนี้ได้
—เป็นทุกโปรแกรมเลยรึเปล่า ?
ไม่ใช่ทุกภาษาที่ดัชชนีอาเรย์เริ่มที่ 0 และจบด้วยความยาวอาเรย์ลบด้วย 1
เช่น.
ภาษาฟอร์แทรน(FORTRAN)
เมื่อประกาศ integer a(10)
จะได้ อาเรย์ที่มีข้อมูล 10 ตัวโดยเริ่ม จาก 1 ถึง 10
แต่ถ้าเราประกาศ integer a(0:9)
จะได้อาเรย์ขนาดเท่าเดิมแต่เริ่มจาก 0 ถึง 9
แต่ภาษาโปรแกรมส่วนใหญ่ออกแบบในลักษณะนี้ เราจึงเห็นมันเป็นส่วนใหญ่เลยละโดยเฉพาะภาษา C / C++, Java ที่ดัชนีอาเรย์เริ่มต้นที่ 0 นั้นเอง
— มากกว่านี้ ?
extra
Why numbering should start at zero — E. Dijkstra
E. Dijkstra ได้เขียนเกี่ยวกับกับการแสดงความต่อเนื่องของ 1,2,3,…,10.
ไว้ในปี 1982 ในปัญหาทั้ง 4 รูปแบบ
a. 0 < i < 11
b. 1 ≤ i < 11
c. 0 < i ≤ 10
d. 1 ≤ i ≤ 10
Dijkstra บอกไว้ว่ารูปแบบที่เหมาะสมควรสามารถทำตามกฏทั้งสองนี้ได้
1). ความต่อเนื่องต้องรวมจำนวณนับที่น้อยที่สุด , 0
2). ความต่อเนื่องนั้นว่างเปล่า (the subsequence is empty)
a. 0 < i < 11
c. 0 < i ≤ 10
อย่างแรก ให้ตัด a. และ c. ทิ้งเลยเพราะมันอยู่ในฟอร์มของ -1 < i
ซึ่งไม่ได้อยู่ในรูปของจำนวนนับนั้นเอง (Dijkstra บอกว่ามันมันน่าเกลียด) หมายความว่าเครื่องหมายตัวหน้าต้องรวมตัวน้อยสุดด้วย(จากกฏข้อที่ (1).) ดังนั้นจึงต้องใช้เครื่องหมาย ≤
เป็นตัวแรก
b. 1 ≤ i < 11
d. 1 ≤ i ≤ 10
ทีนี้เราเหลือ b. และ d. ซึ่งตอนนี้ความต่อเนื่องที่เหลือนั้นเริ่มที่จำนวนนับที่น้อยที่สุดแล้ว ดังนั้นเราจะตัด d. ออกเพราะ ช่วงบนอาจบังคับให้ส่วนหลังถูกทำให้กลายเป็นจำนวนอตรรกยะหรือไม่เป็นจำนวนนับเมื่อลำดับบนนั้นหดจนว่างเปล่า
หมายความว่าเครื่องหมายตัวหลังเราต้องใช้ <
ทำให้สรุปได้ว่า b. 1 ≤ i < 11
คือ สิ่งที่เราต้องการ
ดังนั้นแต่ละครั้งเราก็เลยเขียนว่า
for(i=0; i<n; i++)
{
sum += array[i];
}
อีกทั้งได้มีการลองนำช่วงข้างบนทั้ง 4 ( a,b,c,d ) ไปใช้ในภาษา Mesa
เพราะในภาษา Mesa สามารถนำช่วงทั้ง 4 มาใช้ได้ ปรากฏว่าช่วงที่ไม่แนะนำนั้นได้สร้างข้อผิดผลาดอย่างต่อเนื่อง หลังจากนั้นโปรแกรมเมอร์ที่ใช้ภาษา
Mesa จึงไม่แนะนำอย่างยิ่งให้ใช้ช่วงทั้ง 3 นั้น ( a,c,d ) — E.Dijkstra
“ you are not just following the rules of language notation. You are also promoting mathematical beauty! ”
อ้างอิง — reference.