Python 的 Range 是左開右閉的淮韭,而且除了 Python 的 Range垢粮,還有各種語(yǔ)言,如 Swift 語(yǔ)言的 ..<
運(yùn)算符之類的也有類似這樣的設(shè)計(jì)靠粪。關(guān)于 Range 為什么要這樣設(shè)計(jì)這個(gè)問題蜡吧,Edsger W. Dijkstra 在1982年寫過一篇短文章分析了一下其中的原因——當(dāng)然,那時(shí)候沒有 Python占键,E. W. Dijkstra 當(dāng)年以其他語(yǔ)言為例昔善,但是思路是相通的——這里做摘錄與翻譯如下。
本翻譯同時(shí)發(fā)布于個(gè)人博客
原文
Why numbering should start at zero by Dijkstra
翻譯版
為了表示 2,3,...,12 這樣一個(gè)序列捞慌,有四種方法
- 2 ≤ i < 13(左閉右開區(qū)間)
- 1 < i ≤ 12(左開右閉區(qū)間)
- 2 ≤ i ≤ 12(閉區(qū)間)
- 1 < i < 13(開區(qū)間)
其中有沒有哪一種是最好的表示法呢?有的柬批。前兩種表示法的兩端數(shù)字的差剛好是序列的長(zhǎng)度啸澡。而且在這兩種的任何一種表示法中,兩個(gè)相鄰子序列的其中一個(gè)子序列的上界就是另一個(gè)子序列的下界氮帐。這只是讓我們挑出了前兩種嗅虏,而不能讓我們從前兩種中選出最好的一種表示法來,讓我們繼續(xù)分析上沐。
注意到自然數(shù)是有最小值的皮服。當(dāng)我們?cè)谙陆缛?<
(像第二和第四那樣),如果我們想表示一個(gè)從最小的自然數(shù)開始的序列,那這種表示法的下界就會(huì)是非自然數(shù)(比如 0,1,...,5 會(huì)被表示成 -1 < i ≤ 5)龄广,這種表示法顯得太丑陋了硫眯,所以對(duì)于下界,我們喜歡 ≤
择同。
那我們?cè)賮砜纯瓷辖缌饺耄谙陆缡褂?≤
時(shí),如果我們對(duì)上界也使用≤
會(huì)發(fā)生什么呢敲才?考慮一下當(dāng)我們想要表示一個(gè)空集時(shí)裹纳,比如 0 ≤ i ≤ -1 上界會(huì)小于下界。顯然紧武,這也是很難令人接受的剃氧,太反直覺了。而如果上界使用 <
阻星,就會(huì)方便很多朋鞍,同樣,表示空集:0 ≤ i < 0迫横。所以番舆,對(duì)于上界,我們喜歡 <
矾踱。
有疑問的話恨狈,注意一下,0 ≤ i < 0 的含義是呛讲,i < 0 && i >= 0禾怠,他們之間是邏輯與的關(guān)系,所以當(dāng)上下界數(shù)字相等時(shí)可以表示空集贝搁。
好的吗氏,我們通過這些分析發(fā)現(xiàn),第一種表示法是最直觀的雷逆。我們?cè)賮砜纯从懭藷┑南聵?biāo)問題弦讽,到底我們應(yīng)該給第一個(gè)元素什么值呢? 0 還是 1 膀哲?對(duì)于含有 N 個(gè)元素的序列往产,使用第一種表示法:
- 當(dāng)從 1 開始時(shí),下標(biāo)范圍是 1 ≤ i < N+1某宪;
- 而如果從零開始仿村,下標(biāo)范圍是 0 ≤ i < N;
讓我們的下標(biāo)從零開始吧兴喂,這樣蔼囊,一個(gè)元素的下標(biāo)就等于當(dāng)前元素之前的元素的數(shù)量了焚志。(an element's subscript equals the number of elements preceding it in the sequence. )
總結(jié)
拋開冗長(zhǎng)的分析過程,總結(jié)一下畏鼓,選擇第一種表示法(左閉右開區(qū)間)有以下幾個(gè)原因
- 上下界之差等于元素的數(shù)量
- 易于表示兩個(gè)相鄰子序列酱酬,一個(gè)子序列的上界就是另一個(gè)子序列的下界
- 序列從零(最小自然數(shù))開始計(jì)數(shù)時(shí),下界的下標(biāo)不是 -1(非自然數(shù))
- 表達(dá)空集時(shí)滴肿,不會(huì)使得上界小于下界