[번역] Why numbering should start at zero

[번역] Why numbering should start at zero

2020, Nov 15    

들어가며


오랜만입니다. 블로그 다 죽어가는 것 같아 마음아픈데 심폐소생술 하고자 볼만한 글 하나 번역해볼까 합니다. ㅠㅠ 우리가 질문 던지지 않고 기계적으로 외우고 사고하는 그 문제에 대해서…


우리가 배우는 현대 언어에서 모두 배열의 인덱스가 1이 아닌 0에서 시작한다. 이건 그렇다쳐도 부분수열의 범위를 표현할 때 start index는 inclusive, end index는 exclusive하게 표현한다.(e.x. [1, 2, 3, 4, 5][0:3] == [1, 2, 3] in Python) 내 기억에 이 부분은 프로그래밍에 처음 입문하면 그렇게 쉽지만은 않다. 그래서 오늘은 그 유명한 Dijkstra 교수의 Why numbering should start at zero를 번역했다. 꽤 짧은 글인데 내용이 참고할만하다.

원 글 자체에는 가독성이 그리 고려되지 않은 것 같아 마크업을 내가 추가했으며 글 중간에 예시가 필요하다고 생각되는 부분에는 quote를 넣어 추가했다. 다만 내가 추가한 부분과 원 글은 확실하게 구분되도록 했다.

그리고 번역하는 과정에서 영단어의 뉘앙스를 정확하게 번역했는지 확신이 들지 않는 단어는 영단어를 한글과 병기했다. 또한 영어 문장을 어색하게 직역하는 것을 그리 좋아하지 않아 의역이 꽤나 들어간 것 같다. 조금 어색하다 싶으면 원문을 같이 살펴봐도 괜찮다.

더 나은 표현이 있거나 오탈자가 있으면 댓글로 편하게 달아주시면 확인하고 수정하도록 하겠다.

이 글은 비영리를 목적으로 출처를 남기면 자유롭게 배포 가능하다. Let’s get it.

Why numbering should start at zero


자연수의 부분수열( 2, 3, ..., 12 )을 표기할 때, 이 유해한(pernicious) ...가 붙지 않고자 한다면 네 가지의 선택지가 가능하다.


a. 2 <= i < 13

b. 1 < i <= 12

c. 2 <= i <= 12

d. 1 < i < 13


이 선택지 중 특정한 방법을 더 선호해야 할 이유가 있을까? 당연히 그렇다. a, b 방법은 양측 경계의 차이가 곧 부분수열의 길이와 같다는 것을 알 수 있고 이는 유효하다.

a[i] = (3 <= n < 7)일 때, 7 - 3 == length( [3, 4, 5, 6,] ) == 4

또한 결과적으로 이런 수열들에서는 두 부분수열이 맞닿아 있을 때 한 쪽의 상한수(upper bound)와 다른 한 쪽의 하한수(lower bound)가 같아진다.

a[i] = (3 <= n < 7), b[j] = (7 <= m < 10)로서 둘이 맞닿아 있을 때,
각 끝은 7로 동일

그러나 이런 관측만으로는 a, b 방법 중 하나를 꼭 집어 선택할 수 없다는 것도 유효하다; 따라서 새롭게 시작해보자.



자, 가장 작은 자연수가 있다. b, d 방법처럼 하한수를 제외하면, 가장 작은 자연수로 시작하는 부분수열을 표기할 때 하한수를 비자연수(unnatural numbers)의 영역(realm)에 있는 숫자 중 선택하도록 강제된다.

가령 0, 1, 2, 3 의 숫자 범위를 표현할 때 하한수를 제외하면,
(0 <= n < 4)가 아닌 (-1 < n < 4) 와 같이 표기해야 함.

이것은 보기 흉하며, 따라서 하한수 관련해서는 우리는 <=를 사용하는 a, c를 더 선호하게 된다. 이제 가장 작은 자연수로 시작하는 부분수열을 상상해보자. c 방법처럼 표기 시 상한수를 포함하면 부분수열이 점차 줄어들어 빈 수열이 되었을 때 상한수가 비자연수가 되도록 강제된다.

c[i] = (0 <= n <= -1),  a[j] = (0 <= m < 0) 일 때,
둘 다 빈 수열이지만 a가 더 자연스럽다.

이건 흉하며 따라서 우리는 상한수 관련해서는 a, d처럼 <를 더 선호하게 된다. 결론지으면 부분수열 표기 시 a 방법이 더 바람직하다.



Remark: Xerox PARC에서 개발된 Mesa 프로그래밍 언어는 네 가지의 방법 모두를 사용해서 정수의 간격을 표현하는 특별한 표기법을 가지고 있다. Mesa를 활용한 광범위한 경험실례는 다른 세 가지의 방법을 사용하는 것은 까다로움(clumsiness)과 실수의 지속적인 원인이라는 것을 보여주었다. 이 경험으로 말미암아 Mesa 프로그래머들은 언급된 세 가지 방법을 쓰지 않도록 강하게 권고받고 있다. 내가 이 가치있는 경험적 증거를 언급하는 것은 현장에서(in practice) 확인되지 않은 결론에 불편함을 느끼는 사람들이 있기 때문이다. (End of Remark.)




길이가 \(N\)인 수열을 다룰 때, 우리가 원소들을 인덱스(subscript)로 구분하고 싶을 때 드는 다음 성가신 질문은 어떤 값을 첫 번째 원소의 인덱스에 할당하는가이다. 일반적인 관습을 따라서 인덱스를 1로 두면 인덱스의 범위는 1 <= i < N + 1이 된다. 반면 시작 인덱스를 0으로 두면 표기 시 더 깔끔한(nicer) 0 <= j < N가 된다. 따라서 인덱스를 0부터 시작하도록 하자. 그러면 부여된 서수(ordinal) 인덱스가 “수열에서 이 수의 앞에 있는 수의 개수”라고 생각할 수 있다. 또한 이 이야기의 교훈은 이 지난한 모든 세기들을 지나 마침내, 0을 진짜 자연수로 인식하는 것이 낫다는 것이다.



Remark: 많은 프로그래밍 언어가 이 정도의 당연한 수준의 디테일한 고려없이 설계되었다. FORTRAN은 인덱스를 항상 1로 시작한다. ALGOL 60과 PASCAL에서는 c 방법이 채택되었고 더 최근의 SASL은 FORTRAN 방식으로 회귀했는데 이때 SASL의 수열은 동시에 양의 정수에 대한 함수가 된다. 통탄할 일이다!(Pity!) (End of Remark.)




위의 내용들은 최근에 내 대학에서 컴퓨터 과학자가 아닌 수학자 동료가 어린 컴퓨터 과학자들이 “지식을 뽐내고자”(pedantry) 습관적으로 숫자세기를 0부터 시작한다고 감정적으로 비난했기에(accused) 작성했다. 그는 의식적으로 자신의 주장의 근거로 가장 합리적인(sensible) 관습을 들었다. (또한 “End of …” 에 적힌 방법들이 도발적으로 간주되는데, 그러나 이 방법들은 유용하다. 나는 한 학생을 알고 있는데 그는 암묵적으로 문제들이 첫 페이지의 맨 아래에서 끝난다고 생각해서 시험을 대부분 망치고는 했다.) 내 생각에 Antony Jay가 한 말은 옳다. 그는 “다른 곳과 마찬가지로 종교 공동체(corporate religions)에서 이단자는 그가 틀렸을 가능성이 있어서 내쫓기는(cast out) 것이 아니라 반대로 그가 옳을 가능성이 있기에 쫓겨나는 것이다”고 했다.



Plataanstraat 5
5671 AL NUENEN
The Netherlands
11 August 1982
prof.dr. Edsger W. Dijkstra
Burroughs Research Fellow