我們是不是太關注於語法而忽略了演算法

啟明星工作室發表於2021-06-14

從啟明星數學系統Math說起

最近做了一個數學系統(還沒做完),中間使用了不少第三方開源外掛,但是發現這些外掛基本上都是國外的.

事實上這些外掛基本上都使用Javascript開發,也並不會涉及太高深的JS知識,但是,這些外掛對演算法要求甚高。

(1)數學公式

數學公式使用Latex展示,但是把Latex解析為HTML是非常考驗基本功的技術。

 

(2)SVG畫圖,看起來簡單,但是做起來也不容易,這通常出現在習題裡,例如"三角形ABC,D是BC上一點。。。"類似這樣的題目

 

(3)幾何圖形,包括正弦,餘弦,正切,餘切,指數,對數,微積分,線性變化,圓,橢圓,雙曲線等圖形

這種圖形適合教學,例如通過圖形,很容易讓學生知道正弦餘弦的效果。

 上面這些都是基本功,事實上,他是和語言無掛的。如果JS做不出,那麼用NET/JAVA/GO/等仍然很難做出。

這就像使用AutoCAD進行機械製圖,AutoCAD只是一個工具,如果你設計不同出圖形,那麼無論使用何種CAD,還是作不出。

因此,相比語法,演算法可能更重要。

 

語法與演算法

語法,這裡特指計算機語法,是計算機語言規定的一套規則,不同的語言如Java,NET,甚至Javascript,Typescript都定義了自己的一套語言規則。

要使用該語言,必須符合該語言規則。

演算法,是解決一件事情的方法,或者說是一系列解決問題的清晰指令,同樣一個問題,可以有不同的方法解決,因此演算法有好的演算法也有不好的演算法。

演算法的優劣可以用空間複雜度與時間複雜度來衡量。

軟體=語法+演算法。一個軟體的執行需要“語法+演算法”兩則缺一不可。

 

計算機只要三個語法即可

事實上,早期,人們編寫程式發現,計算機只要三個流程即可:正常的順序流程,條件流程和迴圈流程。

順序流程比較簡單,程式碼一行一行執行,沒什麼可說明的。

條件流程就是 if 語句

迴圈流程就是while語句。

除此以外,其它語句都不是必須的,以.NET為例,其實net還提供了goto語句,但是後來人們發現,goto一方面破壞了程式的可讀性,讓程式跳來跳去,

一方面goto語句可以使用if和whilte替代,所以,goto使用率極低。

掌握了上面的三個流程,就可以寫出程式。

順序的語句

int a=1;
int b=2;
int c=a+b

 

if條件語句

        int a=1;
        int b=2
        if(a<b)
        {
        //do something2
        }
        else
        {
         //do something2
        }  

white迴圈語句

  int i = 0;
        int sum = 0;
        while (i < 10)
        {
            sum += i;
            i++;
        }

 

由此,.NET的其它語法都可以由這3個基本規則推導而來。

例如switch基本上是和if等效的

 switch (i)
        { 
            case "1":
                break;
                   
            case "2":
                break;

            case "3":
                break;
        }

        if(if=="1")
        {
        //
        }

         if(if=="3")
        {
        //
        }

         if(if=="4")
        {
        //
        }

  

 而.NET的 foreach也是可以由while語句實現

string[] studens = { "s1","stud2"};
        foreach (string stud in studens)
        {
            ....
        }

        int len=studens.Length;
        while(i<len)
        {
          string stud=studens[i];
            i++;
        }

 

所以,任何計算機語言都一定會提供if語句和while語句,否則這個語言就無法真正成為計算機語言。

 

演算法是千變萬化

和計算機語言相對穩定相比,演算法才是千變萬化。在計算機教程裡,對排序的演算法講解的最多,包括 簡單排序、插入排序,快速排序,氣泡排序、希爾排序等

每種排序演算法都有優點和確定,例如快速排序雖然快速但是穩定性差, 簡單排序效率差但是穩定性強。

這就像“馬兒跑的快但是力氣小,牛兒力氣大但是走的慢”,所以,牛馬都有各自的應用場景。

 

軟體競爭力核心在演算法

在很多情況下,我們感覺“這個軟體好,那個軟體不好”很大程度上是由演算法決定的,這裡的演算法不僅僅只是排序那麼簡單。

對NET進行序列化和反序列化,主要有微軟提供的DataContractJsonSerializer類和JavaScriptSerializer類,以及開源社群提供的Newtonsoft.Json(JSON.Net)類。

雖然他們都使用.NET開發,但是能明顯感覺Newtonsoft.Json優於微軟提供的類。(圖片來自yanweidie

 

 

 

 

演算法是發散思維的

計算機語言是限定思維的,就是你只能使用他定義的語法,但是,演算法則是發散思維的。這種發散思維體現的是“解決問題的方法”。

當我們在網頁裡,雙擊一個文字時,會自動選擇該文字對應的單詞,

我相信這背後有微軟提供的詞庫,例如你雙擊“歸納”的“歸”,他會自動選中“歸納”,而不是“妨歸”。

 

 

 

但是,在進行svg的操作裡,微軟並未提供這樣的“選中”功能,這就需要我們自己實現“選中物件” 

上次看mrdoob實現的方式很簡單,建立一個span,設定它滑鼠樣式為:none,設定它邊框為紅色,就可以實現下圖的效果。

var selection = document.createElement( 'span' );
		selection.style.position = 'absolute';
		selection.style.display = 'block';
		selection.style.outline = 'solid 2px #ff0000';
		selection.style.pointerEvents = 'none';
		document.body.appendChild( selection );

  

 

類似的例子還有很多。

 

談一談Visual Studio的實現

以下內容純屬猜想,我也沒找他資料來查證下面的猜想。

Visual Studio號稱宇宙開發第一工具,一直很好奇他是怎麼實現的,特別是字型變亮,語法提示,效果又準又快。

好在有開源的力量,最早知道的是codemirror,codemirror可以讓textarea秒變編輯器。

再配合一些外掛,就算非專業人士,也能實現類似部分Visual Studio的效果。

 

 

但是,Codemirror太複雜.

所以,又找到了 PrismJS,這是一個輕量級的程式碼顯示工具,

使用prism能讓你的程式碼,在web上顯示時,看起來很專業。

 

 

很容易看到他提供的原始碼,核心還是“正規表示式”。也就是系統預定義了樣式,當選中所需序言時,切換對應的樣式進行變色。

說起來容易,做起來還是很複雜的。

 

 

當然,Visual Stuido的實現肯定比這複雜,例如VS的關鍵字應該是編譯後顯示亮度,而不是隻靠字面的文字。

雖然leetcode也有演算法,可是她只是一個點,不是一條線。

 --------------------------------------------------------------

啟明星數學系統 http://demo.dotnetcms.org/math,主要是供老師使用的一套系統。

相關文章