艾特某人代码实现_为何敲代码,学好数学很重要?
數(shù)學(xué)是編程的靈魂所在。
作者 | Justin Meiners
譯者 | 王艷妮,責(zé)編 | 屠敏
出品 | CSDN(ID:CSDNnews)
以下為譯文:
程序員喜歡討論編程語言。除了辯論它們各自的優(yōu)點(diǎn)外,我們還喜歡將它們整合到我們的身份認(rèn)知中,甚至通過某人使用的語言來推斷這是一個(gè)怎樣的人。有些人甚至用語言決定論的一種形式爭(zhēng)辯,認(rèn)為思維受限于可被分類的東西的。
由于我們花了很多時(shí)間來使用語言,因此想要使它們變得更好的想法是合理的。然而,這些辯論的特點(diǎn)表明我們認(rèn)為它們代表著更多的東西。也許我們忘記了語言本身最主要的作用。編程語言是實(shí)現(xiàn)工具,而不是思考工具。它們是嚴(yán)格的正式的語言,以人性化的方式來給機(jī)器下指令。相反,思想最好通過一種自由而靈活的媒介來表達(dá)。
用數(shù)學(xué)思考
數(shù)千年來,被高效地用于計(jì)算方面思考的自然語言就是數(shù)學(xué)。大多數(shù)人并不認(rèn)為數(shù)學(xué)是自由的或靈活的。他們?cè)趯W(xué)校看到可怕的符號(hào)和對(duì)解題步驟生硬記憶的經(jīng)歷與自由和靈活的數(shù)學(xué)精神恰恰相反。我希望本文的讀者在數(shù)學(xué)方面有更好的經(jīng)歷,比如在離散數(shù)學(xué)或線性代數(shù)課程中; 那種涉及構(gòu)建清晰的定義和演繹,并用符號(hào)寫成散文(推理步驟)的經(jīng)歷(大多數(shù)符號(hào)甚至直到16世紀(jì)才被發(fā)明)。
數(shù)學(xué)允許你推理邏輯結(jié)構(gòu),而不受其他約束的影響。這也是編程所需要的:創(chuàng)建邏輯系統(tǒng)來解決問題。我們來看一下編程的基本模式:
找出問題所在
設(shè)計(jì)算法和數(shù)據(jù)結(jié)構(gòu)來解決它
實(shí)現(xiàn)和測(cè)試
在實(shí)踐中,工作往往組織得不是那么好,因?yàn)椴襟E之間存在相互作用。你可以編寫代碼來通知?jiǎng)e人設(shè)計(jì)方面的問題。可即便如此,上面這個(gè)基本模式也一遍又一遍地在實(shí)踐中重現(xiàn)。
請(qǐng)注意,步驟1和2是占用我們大部分時(shí)間,能力和精力的步驟。同時(shí),這些步驟并不適合編程語言。這并不能阻止程序員嘗試在他們的編輯器中解決它們,但他們最終會(huì)得到一些混亂,緩慢或解決了錯(cuò)的問題的代碼。并不是編程語言還不夠好。沒有哪一種正式語言在這方面擅長(zhǎng)。我們的大腦就不是那么思考問題的。當(dāng)問題變得困難時(shí),我們繪制圖表并與同事們討論。
理想情況下,首先解決步驟1和2,然后才使用編程語言來解決步驟3。這在轉(zhuǎn)換實(shí)現(xiàn)過程中有額外的好處。有了數(shù)學(xué)解決方案,你就可以專注于選擇最佳的表示和實(shí)現(xiàn)方式,編寫更好的代碼,了解最終目標(biāo)將是什么。
實(shí)現(xiàn)問題
為什么編程語言作為思維工具是繁瑣的?一個(gè)原因是編寫代碼與實(shí)現(xiàn)密不可分。實(shí)現(xiàn)問題對(duì)于給計(jì)算機(jī)下指令是必要的,并且值得做好,但它們也分散了在要解決的問題方面的注意力。想想如果要編寫一個(gè)簡(jiǎn)單的函數(shù),所有的注意事項(xiàng):
我應(yīng)該提供什么輸入?
它們應(yīng)該被命名為什么?
它們應(yīng)該是什么類型的?(即使動(dòng)態(tài)類型語言也必須考慮類型,它是隱含的而已。)
我應(yīng)該通過值還是通過引用來傳遞它們?
我應(yīng)該把這個(gè)函數(shù)放在什么文件中?
結(jié)果是否應(yīng)該重復(fù)使用,或者它是否足夠快以便每次重新計(jì)算?
這個(gè)列表還可以繼續(xù)下去。關(guān)鍵是這些考慮因素與函數(shù)的作用無關(guān)。它們會(huì)分散人們對(duì)該函數(shù)試圖解決的問題本身的注意力。
許多語言旨在隱藏諸如此類的細(xì)節(jié),這對(duì)于普通的日常任務(wù)尤其有用。但是,它們無法超越其作為實(shí)現(xiàn)工具的角色。SQL很容易被認(rèn)為是這方面最成功的例子之一,但它最終關(guān)注的還是表,行,下標(biāo)和類型等實(shí)現(xiàn)方面的問題。正因?yàn)槿绱?#xff0c;程序員仍然在編寫一堆JOIN之前,以隨意的方式設(shè)計(jì)一些復(fù)雜的查詢,比如一些他們想要“獲取”的東西。
不靈活的抽象
編程語言的另一個(gè)限制是它們是糟糕的抽象工具。通常,當(dāng)我們討論工程中的抽象時(shí),我們的意思是隱藏實(shí)現(xiàn)細(xì)節(jié)。一個(gè)復(fù)雜的操作或過程被打包成一個(gè)“黑盒”,其內(nèi)容隱藏,并且暴露出明確定義的輸入和輸出。伴隨著這個(gè)盒子的是一個(gè)關(guān)于它的功能的虛構(gòu)故事,這很容易理解。
黑盒對(duì)于大型系統(tǒng)的工程設(shè)計(jì)至關(guān)重要,因?yàn)榧?xì)節(jié)過多,對(duì)人腦來說理解起來壓力山大。它們也有許多眾所周知的局限性。黑盒泄漏是因?yàn)槠浜?jiǎn)要的說明無法完全表述清楚其具體行為。不透明的界面引入了低效率,例如重復(fù)和分散設(shè)計(jì)。
最重要的是對(duì)解決問題來說,黑盒很僵硬。它們呈現(xiàn)出固定的抽象層級(jí),這個(gè)層級(jí)可能對(duì)問題來說級(jí)別太高或太低。從理論上講,你可以隨時(shí)查看黑盒內(nèi)部,但在代碼中,任何時(shí)候的抽象級(jí)別都是固定的。它們也只提供了一種抽象視角。一個(gè)高級(jí)Web服務(wù)器可以提供用于服務(wù)JSON的極好的接口,但是如果你想要將其用于提供不完整數(shù)據(jù)流的接口(例如來自程序的輸出)那它表現(xiàn)就很差了。
相比之下,數(shù)學(xué)中的抽象一詞與隱藏信息完全不同。這里,抽象意味著提取與特定上下文相關(guān)的某些事物的基本特征或特征。與黑盒不同,這不會(huì)隱藏任何信息。它們不會(huì)以同樣的方式泄漏。我們鼓勵(lì)你調(diào)整到正確的抽象級(jí)別,并在不同角度之間快速跳轉(zhuǎn):
這個(gè)問題最好用表來表示嗎?或者,一個(gè)函數(shù)?
我可以將整個(gè)系統(tǒng)視為一個(gè)函數(shù)嗎?
我可以將這些東西作為一個(gè)整體處理嗎?
我應(yīng)該看整個(gè)系統(tǒng)還是單個(gè)部分?
我應(yīng)該做出什么假設(shè)?我應(yīng)該讓它們更強(qiáng)還是更弱?
只需看看一個(gè)函數(shù)的多種表示方法:
數(shù)學(xué)的主要分支代表了常用的抽象:
幾何圖形從世界中的物體中(或轉(zhuǎn)換不變量,取決于想要獲得的宇宙)抽象出基本形狀。
拓?fù)鋸钠湫螤钪刑崛”砻嫣卣鳌?/p>
群論將二元運(yùn)算抽象為關(guān)于它們?nèi)绾谓M合和反轉(zhuǎn)的屬性。
但是,并不僅限于這幾個(gè)領(lǐng)域。你可以選出對(duì)某個(gè)問題很重要的屬性,并忽略其他。文章最后的示例項(xiàng)目顯示了如何完成此操作。
編程語言非常適合構(gòu)建黑盒; 它們提供了函數(shù),類和模塊,所有這些都有助于將代碼包裝到漂亮的接口中。但是,在嘗試解決問題和設(shè)計(jì)解決方案時(shí),你真正想要的是數(shù)學(xué)那樣的抽象。如果你試著在鍵盤邊上思考,可用的黑盒會(huì)扭曲你的視線。
問題表征
正如編程語言的抽象能力有限一樣,它們?cè)诒硎緮?shù)據(jù)的方式上也受到限制。實(shí)現(xiàn)算法或數(shù)據(jù)結(jié)構(gòu)的行為只是選擇一個(gè)能表示它的許多可能的方式之一。通常,在你了解所需內(nèi)容之前,這還不是一個(gè)你想現(xiàn)在就做出的決定。
例如,圖(頂點(diǎn)和邊的集合)出現(xiàn)在許多編程問題中,例如互聯(lián)網(wǎng)網(wǎng)絡(luò),尋路和社交網(wǎng)絡(luò)。盡管定義簡(jiǎn)單,但選擇如何表示它們很難并且這取決于它們的使用情境:
與定義最匹配的那個(gè):
vertices:vector edges:vector >如果你只關(guān)心連接問題,可以刪除頂點(diǎn)。
如果要快速遍歷節(jié)點(diǎn)的鄰接節(jié)點(diǎn),那么你可能需要一個(gè)節(jié)點(diǎn)結(jié)構(gòu):
Node{id:Int,neighbors:vector }
你可以使用鄰接矩陣。每行存儲(chǔ)特定節(jié)點(diǎn)的鄰接節(jié)點(diǎn):
connectivity:vector >
尋路算法通常在單元板上隱式地處理圖:
walls:vector >
在對(duì)等網(wǎng)絡(luò)中,每臺(tái)計(jì)算機(jī)都是一個(gè)頂點(diǎn),每個(gè)插槽都是一個(gè)邊。整個(gè)圖表甚至無法從一臺(tái)機(jī)器訪問!
數(shù)學(xué)允許你對(duì)圖本身進(jìn)行推理,解決問題,然后選擇合適的表達(dá)方式。如果你使用編程語言進(jìn)行思考,則不能延遲此決定,因?yàn)槟愕牡谝恍写a就是為了特定的表達(dá)而存在的。
請(qǐng)注意,圖的表示太多樣化,無法限于單一種類的接口,類型類(tpyeclass)甚至程序。因此,創(chuàng)建一個(gè)可完全復(fù)用的庫(kù)是不切實(shí)際的。它只能在幾種類型上工作,或者強(qiáng)制所有圖使用不恰當(dāng)?shù)谋硎尽5@并不意味著庫(kù)沒用。類似的表示會(huì)重復(fù)出現(xiàn)(比如std :: vector),但你沒法寫一個(gè)能一勞永逸地解決所有圖形問題的庫(kù)。
一些現(xiàn)代編程語言試圖提供更多的數(shù)學(xué)抽象工具。例如,Haskell有Ring和Group類型類(typeclass)。然而,表示問題表明這些特征肯定不如它們的理論靈感有用。編寫一個(gè)僅依賴于關(guān)聯(lián)屬性并且就那樣存檔的算法是明智的。這就是用數(shù)學(xué)語言思考。但是,實(shí)際上,這只能適度地處理相似類型的小家族。考慮幾種類型的簡(jiǎn)單通用是合適的。
作為必然結(jié)果,編程語言應(yīng)該主要將注意力放在如何做好一個(gè)有用的實(shí)現(xiàn)工具,而不是思考工具上。C在很大程度上做到了這一點(diǎn)。C#的異步和等待等現(xiàn)代語言功能為實(shí)現(xiàn)并發(fā)程序提供了很大的改進(jìn)。
示例項(xiàng)目
那么用數(shù)學(xué)思考是什么樣的一個(gè)過程呢?最近,我在工作中研究了一個(gè)API,它為商家的加密貨幣定價(jià)。它考慮了最近的價(jià)格變動(dòng),并建議商家在動(dòng)蕩時(shí)期收取更高的價(jià)格。
雖然我們?cè)诶碚撋献隽艘恍┕φn,但我們想通過實(shí)證檢驗(yàn)它以了解它在各種市場(chǎng)條件下的表現(xiàn)。為此,我設(shè)計(jì)了一個(gè)機(jī)器人來模擬與我們的API開展業(yè)務(wù)的商家,以了解它的表現(xiàn)。
BTC / USD(1天)
預(yù)備步驟:
定義:匯率r(t)是法定/加密貨幣的市場(chǎng)匯率。
定義:商家費(fèi)率r'(t)是商家被建議向客戶收費(fèi)的修改后的匯率。
定義:當(dāng)客戶購(gòu)買商品時(shí),我們稱該行為是“購(gòu)買”。購(gòu)買包括法定價(jià)格和時(shí)間。p =(f,t)。
定理:通過應(yīng)用修改的匯率t(p)= p(1)/ r'(p(2))找到購(gòu)買的加密量。
證明:p(1)/ r'(p(2))= fiat /(fiat / crypto)= fiat * crypto / fiat = crypto
定義:當(dāng)商家出售他們的加密資產(chǎn)時(shí),我們將該事件稱為銷售。銷售包括加密金額和時(shí)間戳。s =(c,t)。
定理:通過將匯率應(yīng)用于銷售g(s)= s(1)* r(s(2))來找到商家從銷售中獲得的法定金額。
證明:s(1)* r(s(2))= 加密*(法定/ 加密)=法定
定義:一組購(gòu)買和銷售的余額是所有購(gòu)買加密金額和所有銷售加密金額之間的差額。b(P,S)=從t到p(p_i)的i到N之和 - 從j到M的s_j(1)之和
請(qǐng)注意,b(P,S)> = 0必須始終成立。
定義:一組購(gòu)買和銷售的收益是銷售法定金額和購(gòu)買法定金額之間的差額。e(P,S)=(s_j(1))從j到M的總和- p_i(1)從i到N的和> = 0。
目的
定義:如果大多數(shù)典型的購(gòu)買和銷售收入都是非負(fù)的,我們說商家利率是有利的。
r'(t) is favorable iff e(P, S) >= 0.
在一個(gè)有利的案例中,商人通過接受加密并沒有失去任何法定貨幣。
“大多數(shù)”和“典型”的兩個(gè)要求將不會(huì)被嚴(yán)格定義。
作為典型的一部分,我們可以假設(shè)商家會(huì)及時(shí)出售他們的加密資產(chǎn)。因此,假設(shè)s_i(2) - s_j(2)
機(jī)器人的目標(biāo)是驗(yàn)證r'(t)是有利的。
請(qǐng)注意,此定義只是質(zhì)量的一種衡量標(biāo)準(zhǔn)。也許抵制最壞的情況比有利更重要。在這種情況下,我們會(huì)擔(dān)心可能會(huì)進(jìn)行一組收益非常低的購(gòu)買。
算法
重復(fù)多次:
隨機(jī)選擇時(shí)間范圍[t0,t1]。
在[t0,t1]內(nèi)的隨機(jī)時(shí)間生成一組購(gòu)買。價(jià)格應(yīng)該在典型價(jià)格的[p0,p1]范圍內(nèi)。
在[t0,t1]內(nèi)以均勻間隔時(shí)間(可能具有輕微隨機(jī)噪聲)生成一組銷售額。每次銷售應(yīng)該是當(dāng)時(shí)的全部余額。
計(jì)算這些集合的收入。
記錄收入。
后:
報(bào)告有多少收入為負(fù)數(shù),有多少為非負(fù)數(shù)。顯示每個(gè)的百分比。
確定最低和最高收入并報(bào)告。
總結(jié)
當(dāng)你閱讀這個(gè)例子時(shí),我認(rèn)為你的傾向可能是認(rèn)為它的陳述是顯而易見的。當(dāng)然,這些步驟都不是很難。然而,令我驚訝的是,我的許多假設(shè)得到了糾正,選擇有利結(jié)果的客觀定義是多么困難。這個(gè)過程讓我意識(shí)到一些如果我從簡(jiǎn)單編寫代碼開始的話,就壓根不會(huì)考慮的假設(shè)。也許最大的好處是,在編寫之后,我能夠與同事一起快速審查它并進(jìn)行簡(jiǎn)單的更正,但在代碼中很難改變。
我希望用數(shù)學(xué)語言思考會(huì)給你的項(xiàng)目帶來類似的好處!請(qǐng)注意,此示例只是一種利用數(shù)學(xué)思維的方式。我建議讀Leslie Lamport,Udi Manber和Alex Stepanov等等其他人的想法。
原文:https://justinmeiners.github.io/think-in-math/
本文為 CSDN 翻譯,轉(zhuǎn)載請(qǐng)注明來源出處。
下面給大家推薦 CSDN 的好朋友——程序人生。
為什么推薦程序人生?
程序人生聚集百萬程序員,在這里你可以笑談開發(fā)軼事,吐槽百味的程序人生。
無論是從行業(yè)熱點(diǎn)到經(jīng)驗(yàn)解析,從職場(chǎng)困惑到風(fēng)口趨勢(shì),還有程序員不為人知的秘密,我們將為你一一揭曉。
龍泉寺的IT高僧是用哪種編程語言呢?Java ? Python?這篇10W+文章告訴你↓↓↓
程序員下班時(shí),為啥電腦不關(guān)只揣了手機(jī)就走啦??這篇9W+文章過于真相了↓↓↓
調(diào)查上萬名程序員,竟然發(fā)現(xiàn)女程序員比男程序員更懂 Java?怎么回事啊??↓↓↓
總結(jié)
以上是生活随笔為你收集整理的艾特某人代码实现_为何敲代码,学好数学很重要?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: n3k配置vpc是否还需要配置hsrp_
- 下一篇: asmr刷新失败无法连接上服务器_App