<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          計(jì)算機(jī)為什么要從 0 開(kāi)始計(jì)數(shù)?

          共 558字,需瀏覽 2分鐘

           ·

          2020-12-18 17:26

          ?△點(diǎn)擊上方Python貓”關(guān)注 ,回復(fù)“1”領(lǐng)取電子書(shū)

          作者:程序喵大人

          來(lái)源:程序喵大人

          大家好,我是貓哥!


          眾所周知,計(jì)算機(jī)是從0開(kāi)始計(jì)數(shù),而不是我們平時(shí)常用的從1開(kāi)始計(jì)數(shù),但你有想過(guò)為什么嗎?



          其實(shí)不是計(jì)算機(jī)從0開(kāi)始計(jì)數(shù)而是多數(shù)編程語(yǔ)言中的數(shù)組都使用0作為起始下標(biāo),又是為什么呢?


          這個(gè)問(wèn)題超綱了,程序喵不會(huì),但是本著對(duì)科學(xué)的敬畏之心,經(jīng)過(guò)大量的搜索查證,我終于找到了答案。



          故事還要從一位真正的大佬艾茲格·迪科斯徹(Dijkstra)講起,

          艾茲格·W·迪科斯徹Dijkstra
          結(jié)構(gòu)程序設(shè)計(jì)之父

          提出“goto有害論”;

          提出信號(hào)量和PV原語(yǔ);

          解決了“哲學(xué)家聚餐”問(wèn)題;

          Dijkstra最短路徑算法和銀行家算法的創(chuàng)造者;

          THE操作系統(tǒng)的設(shè)計(jì)者和開(kāi)發(fā)者;


          第一個(gè)Algol 60編譯器的設(shè)計(jì)者和實(shí)現(xiàn)者;



          與D. E. Knuth并稱(chēng)為我們這個(gè)時(shí)代最偉大的計(jì)算機(jī)科學(xué)家的人。

          這里貼出我翻譯后的大佬語(yǔ)錄:為了表示自然數(shù)1,2,3,4...14...的子序列,一般有四種序列的表示方法:


          a) 2 ≤?i?< 13

          b) 1

          c) 2 ≤?i?≤ 12

          d) 1


          以上的幾種表達(dá)方式里,有哪一種比其他的好嗎?


          是的,ab有較為明顯的優(yōu)點(diǎn):他們上下界數(shù)值之間的差值就是這個(gè)序列的長(zhǎng)度。在任何一種表示中,兩個(gè)子序列相鄰,最好是其中一個(gè)的上界等于另外一個(gè)的下界,但這還不能抉擇出a和b方式哪種更好,繼續(xù)分析;


          假設(shè)序列里要包含最小的自然數(shù),如果使用bd這種方式,那下界就必須是個(gè)非自然數(shù),這就不太好看了,所以這里更傾向于使用ac的方式,即使用≤方式表示下界。這里如果使用≤表示上界,那一個(gè)空的子序列表示方式也將會(huì)很丑陋,所以對(duì)于上界,大佬的結(jié)論是更喜歡使用ad中的<方式,結(jié)合上一小段的分析,a方式最終獲勝,繼續(xù)分析;


          當(dāng)需要表示一個(gè)長(zhǎng)度為N的序列時(shí),如果想通過(guò)下標(biāo)來(lái)區(qū)分其中的元素,那又來(lái)了一個(gè)棘手的問(wèn)題:初始元素的下標(biāo)值應(yīng)該用多少呢,如果從1開(kāi)始,那范圍變成1 ≤ i < N+1,如果從0開(kāi)始,那范圍會(huì)是0?≤ ?i < N,顯然后一種方式更優(yōu)雅更直觀,所以大佬最后的結(jié)論是自己更傾向于一個(gè)序列的表示最好從0開(kāi)始。



          大佬語(yǔ)錄總結(jié)

          在進(jìn)行范圍表達(dá)的時(shí)候,使用左閉右開(kāi)的方式更優(yōu)雅,他思考過(guò),在處理長(zhǎng)度為N的序列時(shí),到底第一個(gè)元素的下標(biāo)使用0更合適還是使用1更合適?他的出發(fā)點(diǎn)很簡(jiǎn)單,那就是哪種方式更優(yōu)雅。首先確定使用左閉右開(kāi)的方式,當(dāng)下標(biāo)從1開(kāi)始時(shí),下標(biāo)范圍為1<=i



          難道只有優(yōu)雅這一個(gè)原因嗎?其實(shí)下標(biāo)從0開(kāi)始主要的意義是表示偏移,下面舉例:



          數(shù)組為什么起始下標(biāo)是0?其實(shí)數(shù)組是一種線(xiàn)性結(jié)構(gòu),它有一段連續(xù)的內(nèi)存空間,存儲(chǔ)一組具有相同類(lèi)型的數(shù)據(jù)。



          如圖,拿一個(gè)長(zhǎng)度為10的int類(lèi)型數(shù)組舉例,系統(tǒng)就會(huì)為該數(shù)據(jù)分配一段連續(xù)的內(nèi)存空間,空間大小為40個(gè)字節(jié),其中內(nèi)存塊首地址base_address = 100。



          數(shù)組是可以隨機(jī)訪(fǎng)問(wèn)的,當(dāng)訪(fǎng)問(wèn)第i個(gè)元素時(shí),需要定位第i個(gè)元素的地址,定位公式如下:


          第i個(gè)元素地址=base_address + i * data_type_size


          其中data_type_size表示數(shù)組中元素類(lèi)型的大小,int類(lèi)型大小是4字節(jié),所以公式里data_type_size等于4。在這里,下標(biāo)可以理解為偏移,數(shù)組的首地址就是base_address,其中a[0]就是偏移為0的位置,a[i]就是偏移了i個(gè)data_type_size大小的位置,所以計(jì)算a[i]地址的公式為:


          a[i]地址=base_address + i * data_type_size


          這里如果數(shù)組下標(biāo)從1開(kāi)始,那么a[i]地址的公式為:


          a[i]地址=base_address + (i - 1) * data_type_size


          兩個(gè)公式顯而易見(jiàn),下標(biāo)從0開(kāi)始的更加簡(jiǎn)單,后者從1開(kāi)始,每次訪(fǎng)問(wèn)數(shù)組元素都需要額外做一次減法操作,效率更低。



          我們知道在Python中數(shù)組也是將0作為起始下標(biāo),對(duì)此Python之父Guido van Rossum也給出過(guò)正面回答,下面貼出他的翻譯后的語(yǔ)錄:


          大佬語(yǔ)錄

          關(guān)于這個(gè)問(wèn)題之前就有人在Twitter上詢(xún)問(wèn)過(guò)我,我給出過(guò)回答。這個(gè)問(wèn)題我思考過(guò)很久:ABC語(yǔ)言是Python的祖先之一,使用的索引就是從1開(kāi)始的,而另一門(mén)對(duì)Python有重要影響的C語(yǔ)言,它的索引就是從0開(kāi)始。之前的幾門(mén)編程語(yǔ)言(Algol,F(xiàn)ortran, Pascal)有使用1作為起始索引的,有使用某個(gè)變量作為索引。而推動(dòng)我使用0作為起始索引的原因之一就是切片語(yǔ)法。


          讓我們先來(lái)看看切片的用例,可能關(guān)于切片最常見(jiàn)的用法就是“取前n個(gè)元素”和“取從i開(kāi)始的后n個(gè)元素”,如果在使用這兩種用法時(shí)不需要帶有+1或者-1的補(bǔ)償操作,那代碼會(huì)很優(yōu)雅。


          使用基于0的索引方式,那上面兩種切片用法就會(huì)非常漂亮:a[:n]和a[i:i+n],前者是a[0:n]的縮寫(xiě)。


          使用基于1的索引方式,如果你想用a[:n]表示取前n個(gè)元素的意思,要么使用閉合區(qū)間切片語(yǔ)法,要么使用起始索引加切片長(zhǎng)度作為參數(shù)的方法。半開(kāi)區(qū)間切片方法如果和基于1的索引方式結(jié)合起來(lái)那代碼將會(huì)變得不優(yōu)雅。而如果使用閉合區(qū)間切片語(yǔ)法的話(huà),為了從第i位索引開(kāi)始取n個(gè)元素,那就需要把表達(dá)式寫(xiě)成a[i, i+n-1]。這樣看來(lái)也許使用切片起始位+長(zhǎng)度的方式在基于1的索引方法中更合適?這樣你可以寫(xiě)成a[i:n],并且ABC語(yǔ)言就是這么做的,你可以寫(xiě)成a@i|n這種特別的語(yǔ)法。


          但是,index:length這種方式在其它情況下也適用嗎?我有點(diǎn)記不清了,但我認(rèn)為我確實(shí)是被半開(kāi)區(qū)間這種優(yōu)雅的語(yǔ)法迷住啦。特別是當(dāng)兩個(gè)切片操作相鄰時(shí),第一個(gè)切片的終點(diǎn)索引是第二個(gè)切片的起始索引時(shí),這種語(yǔ)法簡(jiǎn)直太漂亮啦。例如你想要將一個(gè)字符串使用i和j分成三部分,這三部分會(huì)是a[:i],a[i:j]和a[j:],真是太漂亮啦。


          這就是為什么Python使用0作為起始索引的原因。

          看到這里你知道為什么很多編程語(yǔ)言都是從0開(kāi)始計(jì)數(shù)了嗎?

          另外,關(guān)于列表和索引,我們之前也介紹過(guò),推薦閱讀:超強(qiáng)匯總:學(xué)習(xí)Python列表,只需這篇文章就夠了



          參考資料


          https://www.cs.utexas.edu/~EWD/transcriptions/EWD08xx/EWD831.html


          https://blog.csdn.net/csdnsevenn/article/details/107421466


          https://docle.github.io/2018/08/26/Why-Numbering-Should-Start-At-Zero/


          https://www.reddit.com/r/Python/comments/1p2za1/guido_van_rossum_why_python_uses_0based_indexing

          Python貓技術(shù)交流群開(kāi)放啦!群里既有國(guó)內(nèi)一二線(xiàn)大廠(chǎng)在職員工,也有國(guó)內(nèi)外高校在讀學(xué)生,既有十多年碼齡的編程老鳥(niǎo),也有中小學(xué)剛剛?cè)腴T(mén)的新人,學(xué)習(xí)氛圍良好!想入群的同學(xué),請(qǐng)?jiān)诠?hào)內(nèi)回復(fù)『交流群』,獲取貓哥的微信(謝絕廣告黨,非誠(chéng)勿擾?。?/span>~

          近期熱門(mén)文章推薦:

          Python 幕后解釋器:一系列的學(xué)習(xí)資源
          當(dāng)我發(fā)現(xiàn)國(guó)際友人翻譯了我的文章之后……
          Python 的縮進(jìn)是不是反人類(lèi)的設(shè)計(jì)?
          Python到底是強(qiáng)類(lèi)型語(yǔ)言,還是弱類(lèi)型語(yǔ)言?

          感謝創(chuàng)作者的好文
          瀏覽 28
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产丝袜足交在线观看 | 日韩成人app | 熟女婷婷网| 三级片中文字幕 | 亚洲视频欧美色图 |