如何以計算機的方式去思考?

2021-03-02 頂級程式設計師

源 / cnblogs    文 / ChaosYang1987

從上大學第一天開始接觸編程,老師便給我們講過各式各樣的算法。從各種查找、排序,到遞歸、貪心等算法,大一的時候一直在和這些算法搏鬥。直到工作後,為了應付面試,仍不得不回過頭去啃算法書或者去刷一些算法習題,才能夠拾回一些上學時的記憶。為什麼算法就這麼難以記住呢?或者說,為何計算機的算法不能更直觀一些呢?因為計算機的算法就是反人性的,從本質上來說,這是計算機的思維方式和人腦思維方式的區別而造成的。人腦思維的機制至今沒有一個確定的理論,暫時認為是化學物質和電信號的作用。雖然沒有科學的解釋,但是我們每個人都有一顆大腦,我們每個人都可以感受到自己的思維方式。而計算機則是人類創造的,從設計之初它便不是以模擬人腦為目的,因此它有其獨特的工作方式,只有理解了計算機的工作方式,才可以學會以它的方式去思考, 才可以寫出最適合計算機運行的程序代碼。在排序數組中尋找特定數字 —— 人腦 vs 計算機 round 1我們通過一個具體的例子,來說明人腦和計算機的思維方式不同,假設我們想要從一個已經排好序的數組中找出一個特定的數字。已知排序好的數組是1 2 3 5 7 13 34 67 90 127 308,我們希望找到是否13這個數在數組內。人腦處理這樣的問題幾乎是「作弊」的,我們可以一目十行,我們在眼鏡一掃視的情況下就發現了13,所以如果我問自己我是如何找到13的,我只能說我「看見」了。最簡單也是最笨的算法就是從數組開始一個一個的讀入數組,我相信每個學習過編程基礎的同學都可以寫出類似下面的代碼。
boolean isNumInArray(int num, int[] array) {    for (int i = 0; i < array.length; i++) {        if (array[i] == num) {            return true;        }    }    return false;}

計算機需要從數組的第一個元素開始,一個一個的去查當前的數組的元素,和13相比,看看是不是相等。為了找出13這個數,計算機要做6次循環操作,而人幾乎是瞬間就看到了答案。為何計算機解決問題的方式這麼「笨」呢?我們先得從計算機的工作原理說起。CPU的工作方式CPU作為計算機的最核心的部件,也是算法的主要運載體。CPU並不會像人一樣思考,它只懂得一些基本的指令。每一個CPU都有其指令集,指令集是存儲在CPU內部,對CPU運算進行指導和優化的硬程序。通俗一點說,指令集就是CPU的所有思維方式。比如常見的指令集中都會有ADD指令,這個指令可以將兩個寄存器中的值相加,並將存儲到另一個寄存器中;與此相對應的也會有SUB指令,用於將兩個寄存器值相減。如果你去查閱各種CPU指令集的手冊,會發現基本上都會包含基本的加減乘除指令,以及向內存中存、取數據的指令。而常見的CPU指令集,最多也就是幾百條指令。也就是說CPU只會這幾百個命令。而人腦相對於CPU,有強大的記憶和聯想能力,比如你看到1+1,就想到2,看到紅燈,就會想到停下來,看到門,就知道去開門把手,這些都是你不假思索可以立刻反映出來的東西。所以,CPU會的東西(指令)比人少多了,那CPU豈不是很笨?沒錯,CPU就是很笨,但是CPU的優點也是人腦所無法比擬的:雖然CPU只會幹簡單的事情(幾百種指令),但是它可以在固定的時間(指令執行時間)內保證正確的運算出正確的結果。而人腦不可能保證在固定的時間內一定產生「同樣」的思維結果。現代化的CPU工藝可以在一秒鐘內執行百萬次以上的指令,而人腦的思維速度則比不上,我們一個「念頭」最短也需要零點零幾秒的反應時間。計算機存儲計算機的常見存儲有寄存器、高速緩存、內存、硬碟等。寄存器就相當於人腦中立刻可以想起來的東西,CPU所做的一切運算都是針對於在寄存器中的數據進行的。寄存器存儲了計算機當前要做什麼計算(指令寄存器),要計算的數據(數據寄存器),計算到哪一步了(段寄存器)等信息。無論是最早的有寄存器的CPU還是最新最強的的CPU,它們的寄存器數量最多也只有幾十個(特殊情況有幾百個),也就是說CPU同一時刻能夠立刻使用過的信息也就是這幾十個數字。內存則是計算機的主力存儲設施,它可以存儲運行中的程序的信息,內存相當於圖書館的書架,CPU需要用某一段內存中的數據是,需要通過LOAD指令,同時附上一個書架編號(內存地址),然後內存控制器可以將對應的地址的數據通過總線傳輸給CPU,CPU則將載入的結果放入寄存器中使用。內存存取的速度遠小於寄存器,但是訪問分布在內存各個區間的數據的速度基本是相等的。由於大部分時候CPU需要讀取連續的一段內存來進行運算,因此通常CPU會有高速緩存將最近使用過的內存整塊緩存起來,而使得CPU不必每執行一步就需要去讀一次內存。高速緩存的速度介於寄存器和內存之間,但遠高於內存。高速緩存的大小一般在幾兆到十幾兆之間。硬碟屬於外部存儲,老式的機械硬碟中會有一個可轉的磁頭,在讀取磁碟文件的時候需要將磁頭轉到對應的位置,磁碟的速度遠低於內存,並且如果磁碟的磁頭如果停留在某個位置時,隨機磁碟上不同位置的信息,會受到磁頭運動的物理速度限制而出現速度不均等的情況。新式的固態硬碟採用了和內存相似的存儲介質,在隨機訪問的性能上提升很大。所以,計算機有一顆只能記得一點點事情的小腦袋(寄存器),但是能夠擁有相對較大的快速記憶(緩存),擁有遠超過人類的知識儲備(內存),並且還隨身攜帶了巨大的移動圖書館(硬碟),所以從存儲上來看,計算機像是一個有先天缺陷的雨人(Rain Man)。所以,我們來分析一下round 1中為何計算機到底做了怎樣的操作?
boolean isNumInArray(int num, int[] array) 

在調用函數的底層實現中,參數是被分配到兩個寄存器中。isNumInArray這個函數,在被調用時,第一個參數num的值13會被載入到寄存器(r1), 的第二個參數array,傳入CPU的時候就只是array在內存中的地址信息,被存儲在另一個寄存器(r2)。而在第四行array[i] == num時,CPU需要做三件事才可以完成這工作:通過ADD指令,根據array的地址(r2)和i(r4)的數字,計算需要讀取的內存地址通過LOAD指令將內存地址對應的數載入到寄存器(r3)通過CMP指令比較num(r1)和r3的值,結果存儲在結果存儲器中而根據操作3的結果,如果結果不相等,則CPU需要將循環計數器i加上1存入寄存器r4,再次進行上面的計算。所不同的是,第二到第N次的步驟二會比第一次要快很多,因為整個數組的內容已經被高速緩存所捕獲。所以,我們可以看出為何計算機在解決這個問題上顯得如此愚笨:計算機的輸入收到限制。計算機一次只能讀入單個值(有高速緩存的幫助這並不太糟糕),且在寄存器中放有限的幾個值,而人類可以通過視覺等一次性讀入多個值存儲在腦海中。計算機的指令有限制,只能支持基本的運算指令。而人腦可以有豐富的指令,比如直接通過一堆剛剛看到的數字中視覺模式匹配出13這個數字。在排序數組中尋找特定數字 —— 人腦 vs 計算機 round 2計算機在上一輪和人腦的PK中敗下陣來,然而這並不是很公平,因為數組的數量只有短短的幾個,而計算機可以存儲的上限遠不止於如此。於是我們開始第二次的比拼。這次我們將輸入擴大1 2 3 5 7 13 34 67 90 127 308 502 ... 2341245 ... (100萬個對於一個普通人,我們假設這100萬個數字是列印在一本字典裡的,那麼他如何找出100萬個有序數組中的某個數字呢?這時人類引以自豪的「一目十行」的能力已經微乎其微,當數字的位數增大時,且不說一眼比較一個數字是否和目標數字相同已經困難,即使真的有一目十行的本事,在100萬這樣的數字面前也是微乎其微。於是乎,我們老老實實的去從頭到尾比較數字,一頁一頁的翻開,去看當前的頁中有沒有數字,沒有的話就去翻下一頁。這個思路是不是很熟悉?沒錯,這就是計算機的思維,和我們上一節中所描述的計算機編碼幾乎是一樣的,除了人可以一眼多看幾個數據外。然而,人類在比較大數是否相等的速度,以及翻字典的速度可遠遠比不上計算機去讀完這100萬個數的速度,同樣是「笨鳥」,計算機每秒百萬次的運算能力幾乎可以在瞬間就完成這樣的任務。也就是說,在大規模輸入的情況下,人腦的思維方式「退化」成和計算機近似,但是被計算機壓倒性的性能優勢給擊敗。在排序數組中尋找特定數字 —— 人腦 vs 計算機 round 3在第二輪中,人腦敗給了計算機,但這樣的比拼無疑於兩隻笨鳥比誰更快。有沒有聰明一些的方法呢?沒錯,我們學過二分查找(Binary Search)的算法可以派上用場了。步驟一:有這麼有一本列印了100萬個數字的字典擺在我們的面前,我們不知道要找的數字會在哪裡,那麼我們先折半打開字典(不用那麼精確也沒關係),看當前頁的第一個數字和最後一個數字,我們要找的數字是否在這個範圍內,如果在那麼我們可以繼續在當前頁找這個數字。步驟二:如果當前頁的第一個數字還是比我們要找的數字大,那麼我們可以將字典的後半部分撕了(因為我們要找的數字不可能在後半部分了),繼續上面的步驟。步驟三:如果當前頁的最後一個數字比我們要找的數字小,那麼我們可以將字典的前半部分撕了(理由同上),繼續步驟一。這樣我們會講這本字典越撕越薄,最壞的情況下我們會撕到最後一頁,這一頁要麼有這個數字,要麼沒有這個數字,但是我們保證按照上面的步驟進行我們不會錯過任何可能含有這個數字一頁。這個邏輯和計算機算法中的二分查找原理是一樣的,我們來看看實際的算法代碼是如何實現的
boolean isNumInArray(int num, int[] array, int start, int end) {        if(num < arr[start] || key > arr[end] || start > end){        return false;                   }        int middle = (start + end) / 2; if(array[middle] > num) {        return isNumInArray(arr, key, start, middle - 1); else if(array[middle] < num){        return isNumInArray(arr, key, middle + 1, end); else {        return middle;    }   }

我們可以看出,和人類的思維方式比,計算機不會翻「一頁」,它只會翻看一個數字,但是其他的思維方式是一模一樣的。利用這樣的算法,人類雖然從結果上還是比計算機要慢,但是雙方都找到了最適合的方法,達到自我效率的最大提升。在排序數組中尋找特定數字 —— 更多的思考那麼我們回過頭來看,為什麼我要假設這100萬數字列印在字典上呢?因為字典和計算機內存的模型很像。計算機可以通過內存地址來直接訪問內存,這一點和通過字典的頁碼來翻到某一頁,這一點是近似的。在計算機編碼中我們可以知道數組的長度,而通過折半的方法找到中間的數,字典有厚度,我們可以通過厚度減半來找到中間的頁碼,這一點也是相似的。試想一樣,如果100萬的數字不是列印在字典,而是印在一條公路上,我們是否還可以用上一節的算法來人肉二分查找?答案是不可以,因為跑到公路的一半會消耗你很多的體力,如果採用二分法查找比起round 1中的最笨辦法只會讓你耗費更多的體力。因為公路這一存儲的概念,對應的便不是內存的模型,而是磁帶(Tape)的模型,那麼對於這樣的模型,我相信不論是人或者是計算機, 都需要調整算法,來達到最高的效率。總結通過以上的例子,我們可以看到,計算機的算法反人性,是因為計算機不是一個「正常人」,它有自己的缺陷,也有自己的長處。很多時候我們覺的算法不直觀,不是因為我們的思維能力比計算機差,而恰恰是因為作為人類我們同時接觸的信息太多,所會的東西也太多而阻塞了我們的思維。那麼這種時候,不妨將自己「墮落」成一臺「鼠目寸光」和「所知甚少」的計算機,這時可能會有更清晰的思路。

-END-

【讀者福利】9.9元Python編程課

互動對話教學+在線編程

專為零基礎小白打造

百元獎學金紅包免費領

限時24h,速速搶購👇

相關焦點

  • 資料|像計算機科學家一樣思考Python(中文版)
    from=leiphonecolumn_res0903內容簡介 · · · · · ·《像計算機科學家一樣思考python》按照培養讀者像計算機科學家一樣的思維方式的思路來教授python語言編程。全書貫穿的主體是如何思考、設計、開發的方法,而具體的程式語言,只是提供一個具體場景方便介紹的媒介。
  • 讓人「雲裡霧裡」的計算機科普——計算機科學普及的現狀與思考
    在新形勢下,弘揚科學精神,傳播科學方法以提升科學素養更是一個長期過程,這對研究人員產生了新的、對科普能力的要求,自然也提出了新問題:作為科研人員又該如何科普?對比物理知識科普,分析計算機科學普及的現狀,或許能引發一些思考。
  • 視點|讓計算機科學真正流行起來——計算機科普的現狀與思考
    2019年的一次意外事件,引發了我對科學普及的重新認識和深刻的思考。2019年初我帶女兒看科幻電影《流浪地球》之後,給女兒畫了6張手繪圖講解其中的科學知識。我的主要研究領域是大數據與人工智慧,2013年我們在《計算機學報》上發表的文章《網絡大數據:現狀與展望》,下載量達到7萬次歷時近7年,而我的手繪科普圖實現過億閱讀,只用了7天時間。這讓我深切意識到大眾對科學知識的需要和對科研人員參與科普工作的認可。根據近期的思考,我認為推動計算機科學普及需要從品牌、產品和生態三個方面著手。
  • 對話孔子|如何用哲學方式去思考和閱讀《論語》?
    隈研吾的看法是否正確姑置不論,重點是他對本身不是哲學作品的現代混凝土建築施以了哲學思考。換言之,他「哲學地」閱讀、思議、考察、檢視了它們。這樣看來,我們也不妨暫時把「《論語》是不是哲學文獻」的問題擱置起來,轉而討論:如何哲學地閱讀《論語》?以下將剖析五種哲學地閱讀《論語》的可能方式。
  • 計算機大數乘法引發的思考|CSDN 博文精選
    但我一下子想不到怎麼拆解,我也懶得思考,因為我在思考另一件事。我比較善於寫一些思考的過程。所以,我們按照相對常規的思路,循序漸進地來思考如何來優化程序。記住,準則只有一個,即讓計算的步驟變少!看看上面的代碼,算法完全模仿人類的手工豎式,按照十進位一位乘法來推進計算過程。但是這裡面有個根本的問題,猜猜看是什麼?
  • 計算機大數乘法引發的思考 | CSDN 博文精選
    但我一下子想不到怎麼拆解,我也懶得思考,因為我在思考另一件事。原式=67×3×33×707+11×44×9×707=67×3×33×707+11×44×9×707=11×99×707=111×99×7×101=777×9999=7770000−777=7769223通俗來講,一個計算的所有步驟就是一個算法,算法的時間複雜度其實就是計算的規模和步驟數量之間的關係。
  • CCCF專欄 | 如何以計算的視角來思考
    在某個時刻,我們或許需要探尋惠子和墨家是如何參與到其中的。當我們討論計算思維時為何要從哲學家開始?因為計算思維關注於教育,而這種教育並非出於培養計算機科學家或工程師的目的,而是為了啟迪普羅大眾。因此,我們從哲學——而不是從數學、工程或是邏輯學開始。其基本想法是,計算思維應該教會人們該如何更清晰地去思考這個由數字計算所創造的世界。
  • 蘋果CEO庫克演講:我更擔心人們像計算機一樣思考
    庫克說:「我所擔心的並不是人工智慧能夠像人一樣思考,我更擔心的是人們像計算機一樣思考,沒有價值觀,沒有同情心,沒有對結果的敬畏之心。這就是為什麼我們需要你們這樣的畢業生,來幫助我們控制技術。」那麼該如何實現技術的價值呢?為什麼庫克又說賈伯斯為他的人生指明了方向?
  • 專訪德國漢學家薛鳳:當歷史學家和計算機工程師同桌思考
    薛鳳掌舵的德國馬普科學史研究所在數字人文研究方面是先行者,她在專訪中說:「在我們所,計算機工程師和歷史學家是坐在一起研究的。歷史學家可能提出一個問題,然後計算機工程師負責跟歷史學家一起思考,怎麼樣用計算機方法來處理這個問題。」
  • Win7中右鍵計算機無法打開計算機管理的解決方式
    某一天,突然就無法在右鍵計算機的右鍵菜單中打開計算機管理要進行一些任務計劃程序的設置也變得只能去控制面板中打開,當然也可以在運行中輸入計算機管理的命令行來打開,但這與平時的習慣差別就比較大了!右鍵單擊計算機——管理後,彈出下面的提示窗口,應該怎麼做呢?
  • 顛覆思維方式:教師如何培養出有自己思考的「閱讀者」?
    《顛覆性思維:為什麼我們的閱讀方式很重要》將這些老師從未思考過的閱讀教學問題一一呈現出來,並提供了良好的教學示範。」什麼才是真正的閱讀?作為老師,你有沒有發現,你的學生在閱讀過程中出現了各種各樣的問題:只是為了應付考試而閱讀,不會主動去讀額外的文章;只是從文本中提取信息,而不能深入理解內涵;總是全盤接受文本中的所有觀點,而沒有自己的思考。
  • 如何理解計算機知識及計算機發展史
    大家好,這裡是鏈客區塊鏈技術問答社區,今天講一講如何理解計算機知識,以及計算機的發展史。也感謝大家的關注~計算機是標準的理工科而不是文科,所以你要了解的不是它的歷史,而是它最最基本的核心概念,以及後續的概念是如何由此逐步建立起來的評論有人提出了類似的疑問,希望了解到底計算機是如何發展成這樣的,所以我編輯一下答案提供個大概的框架在我看來,想充分的解答這個問題,需要的是份詳細的CS「本科階段的課程踣線,而不是簡單的三言兩語的科普就能解決的,所以我只能提供一個總體的方向性的東西
  • 孩子必備的計算機思維,如何從生活中培養?
    因為編程中蘊含的計算機思維,幫助孩子更好地思考。什麼是計算機思維將一個困難問題分解,通過邏輯分析和細分步驟構思出解決方案,從而形成解決問題的模型,再將該模型應用到更多同類問題當中的思維方式。計算機思維的重要性隨計算機科學的發展和應用的普及,這個世界越來越數據化。實物和各類信息,比如名畫、樂譜、人們的關係等等,都通過數據信息的方式被保存下來,也因此越來越多的問題可以通過數據分析與計算的方式解決,也就是使用計算機思維去找到解決方案。所以,計算機思維也就越來越重要。
  • 又快又準找到真實問題的思考方式,是如何養成的?
    所以,麥肯錫諸多工作方法中,有批判性思考的方法,即通過深刻洞察得出自己想法。而鍛鍊批判性思考有一條習慣是:嘗試一下蘇格拉底方法——提問。又有一次,大家反饋衛生間異味重,建議外面再安一道門。行政的一位同事回覆說:啟用新的抽水泵就可以了。
  • 如何培養數學家的思維方式?
    本書是用新思維去認識宇宙的科普佳作,也是一本了解科學方法與諾貝爾獎大師思考方式的啟發式讀物。只要你認真閱讀下面的這篇文章,思考文末提出的問題,嚴格按照互動:你的答案格式在評論區留言,就有機會獲得獎品!作者:Waldo Otis翻譯:Nuor審校:xux如果問「一個數學家是如何思考的」,就類似於問「一位音樂家是如何創作的」。同樣的,這個問題可以用來了解創造性的工作是如何進行的。
  • 研究生們如何「宅」在家裡搞好科研: 給計算機應用技術專業研究生...
    本文圍繞計算機應用技術專業研究生如何充分利用「宅」在家裡的寶貴時間加強學習思考、豐富知識結構、訓練思維方式,提出一些建議,希望對同學們有所幫助。因水平有限,時間倉促,難免有不足甚至謬誤之處,敬請批評指正。
  • 我們應該學習計算機技術,而且我們更應該學習計算機編程
    01我們都應該學習計算機技術,而且我們都應該學習計算機編程。請一定要注意,我們都應該學習計算機技術,這句話幾乎每個人都會認同,因為現在連小學生都開設了計算機的課程。計算機的廣泛應用,改變了我們的工作、學習、生活和娛樂方式,所以我們每個人都應該學習計算機技術。
  • 當你遇到問題需要解決的時候你是如何思考如何去做呢
    有個詞,叫「第一時間思考力」,一件事情出來,你「第一時間」想到什麼,會做什麼,很能反映出一個人的思考方式。心理學家將這種思考,稱之為「第一時間思考力」。如何能快速處理問題,解決問題呢?在很多場景中都需要我們在有限的時間內去解決問題,比如你的領導布置了一個任務需要你儘快完成,此刻你應該如何去做呢?首先就需要你對領導安排的工作有大體的思路,搭建起很明確的框架出來,然後再去細化,把領導給的方案圓滿完成。
  • 數學家可以被計算機取代嗎?計算機解釋不了事物的真實性
    1998年著名的克卜勒猜想,它指的是如何堆積一些圓球使得它們佔據的空間最小,對這個猜想的證明我們更多的藉助於計算機。 相反,我們可以使用ATPs,以數學方式驗證特定硬體系統或運行在其上的代碼是否正確,並始終按其應該的方式運行。 ATPs仍然需要大量的人工輸入來工作,但Pitts相信,至少在計算機科學中它正引起巨大的變化。許多數學家可能會覺得這種發展有點悲哀:正如Pitts指出的,這意味著人們不再關心如何使數學論證變得優雅。
  • 它到底是計算機還人的思維方式?
    周以真認為:計算思維是運用計算機科學的基礎概念去求解問題、設計系統和理解人類行為的,它涵蓋了計算機科學的一系列思維活動。後來,國際教育技術協會(ISTE)和計算機科學教師協會(CSTA)於2011年給計算思維做了一個可操作性的定義,即:計算思維是一個問題解決的過程,該過程包括以下特點:1,制定問題,並能夠利用計算機和其他工具來幫助解決該問題。