揭秘你處理資料的“底層邏輯”,詳解公式引擎計算(二)

上篇中我們介紹了計算公式引擎的計算原理,本期我們繼續帶著大家瞭解在Excel表格中公式引擎的實現原理。

背景

在上節中解決了基本運算的邏輯之後,在一些實際業務場景中,公式計算並不是單一公式進行的獨立運算。我們經常需要將一個很大的運算分解成前後依賴的小運算;同時這些單元格之間的計算會出現很多相互依賴,計算順序也是要考慮的一個關鍵問題,我們需要將一系列具有先後順序的同類運算管理起來依次執行。

為了實現這種計算關係之間的管理,出現了計算鏈,用以對公式之間的依賴和先後順序進行管理,處理在電子表單中錯綜複雜的依賴。涉及到圖的處理,髒值計算等內容。接下來我們將從圖計算出發,介紹不同圖的計算、按需計算和髒值處理的問題,更加深層次的瞭解Excel表格計算中計算鏈相關問題。

計算鏈

讓我們先從兩個表格計算問題出發。

第一種簡單情況:

揭秘你處理資料的“底層邏輯”,詳解公式引擎計算(二)

在這一串計算公式之中,當C1賦值為1時,A1的結果為3。但此時如果修改C1的值,C1=10,此時B1的內容還沒有修改,A1依舊是3,然後B1=10+1=11,這裡就會發現A1內容計算出錯。

第二種更加複雜一些的情況:

揭秘你處理資料的“底層邏輯”,詳解公式引擎計算(二)

我們用圖的結點表示單元格的計算內容,箭頭代表依賴關係。入度為零的節點,完全不依賴其他節點內容,所以計算的順序應該是從不依賴其他節點的節點內容開始。單元格A依賴F、E,D依賴C、B,C、B又分別依賴F、E,唯二不依賴其他節點的內容是E、F。

這樣就得到了一個穩定正確的計算順序,這個順序被稱之為計算鏈。在這個例子中計算鏈是:F,C,E,A,D,B。

有向無環圖和有向有環圖的計算

在一張圖中,如果從一個節點出發,最後能回到這個節點,我們稱之為有向有環圖,反之被稱作有向無環圖。

揭秘你處理資料的“底層邏輯”,詳解公式引擎計算(二)

左圖中不論從任意一個節點出發都不能再回到該節點,所以左圖是有向無環圖。

右圖中A點可以出發後回到A節點,所以右圖是有向有環圖。

我們將計算節點和計算節點之間的關係拆解成有向圖後,就可以使用計算有向圖的標準方法得到一個可靠的計算鏈。

1、有向無環圖的計算

對於每一個節點存在入度和初度的概念,入度:多少箭頭指向當前節點,例如對於A節點,入度為1;出度:當前箭頭有多箭頭指出,例如對於B節點,入度為2。

在對有向無環圖進行計算的時候,就利用了圖中入度作為優先順序排序,每次運算入度為0的節點,然後移除。

揭秘你處理資料的“底層邏輯”,詳解公式引擎計算(二)

以上圖為例,完整的計算過程如下:

1。初始化,統計入度: A:1 B:2 C:1 D:2 E:0 F:0

2。 計算 E 節點,更新入度: A:1 B:2 C:0 D:2 F:0

3。 計算 F 節點,更新入度: A:1 B:2 C:0 D:1

4。 計算 C 節點,更新入度: A:1 B:1 D:0

5。 計算 D 節點,更新入度: A:1 B:0

6。 計算 B 節點,更新入度: A:0

7。 計算 A 節點,計算結束有向有環圖的計算

2、有向有環圖的計算

解決了有向無環圖的計算問題,如果此時把上圖中B-C之間的箭頭反向調換,情況就會變的截然不同起來。此時B-C-D之間組成了一個環。

揭秘你處理資料的“底層邏輯”,詳解公式引擎計算(二)

這時候依舊進行計算:

1。

初始化,統計入度: A:1 B:1 C:2 D:2 E:0 F:0

2。

計算 E 節點,更新入度: A:1 B:1 C:1 D:2 F:0

3。

計算 F 節點,更新入度: A:1 B:1 C:1 D:1

4。

沒有入度為0的節點,開始迭代計算

(迭代計算:把上一步的計算結果代入這一步的運算中去,經過多步這樣的計算,可以得出一個更為接近的結果。)

按需計算

解決這種互相依賴的複雜單元格的運算時,除了圖計算還可以採用按需計算的方法。在這裡使用到的是calcOnDemand這個函式。這個函式的核心工作原理是:壓棧並且計算所需要的節點內容,該節點可以是任意內容。

揭秘你處理資料的“底層邏輯”,詳解公式引擎計算(二)

以該圖內容來說明這一計算的過程:這裡選擇A作為我們需要的節點

壓棧並計算A,需要計算B的結果

壓棧並計算B ,需要計算C的結果

壓棧並計算C ,需要計算E的結果

壓棧並計算E, E 計算完畢後出棧

計算C,C計算完畢後出棧

計算B,還需要計算D的結果

壓棧並計算D ,拿到C的結果,還需要F的結果

壓棧並計算F, F計算完畢後出棧

計算D,D計算完畢後出棧

計算B,B計算完畢後出棧

計算A,A計算完畢後出棧

棧空,計算完畢

揭秘你處理資料的“底層邏輯”,詳解公式引擎計算(二)

這個例子取了最複雜的A作為需求節點,如果需要D節點,變為D節點入棧,C節點入棧,E節點入棧,計算後出棧,C節點計算後出棧,F節點入棧計算後出棧,D節點入棧,這樣就得到了正確的D的值,這種運算方式只計算需要的內容。

圖計算VS按需計算

在這裡對圖計算和按需計算做一個對別,這兩種演算法在不同情況下效率不同。

揭秘你處理資料的“底層邏輯”,詳解公式引擎計算(二)

左圖中是一個從上到下的累加,使用按需計算計算的很順暢,從上向下按順序計算即可,堆疊中存在的待計算元素不超過兩個,按需計算比圖的計算更加快。

右圖中是是一個逆向計算,上一行單元格的內容依賴下一行單元格的內容,按需計算需要計算1000步,這時按需計算會比圖計算慢很多。

揭秘你處理資料的“底層邏輯”,詳解公式引擎計算(二)

總體來說,圖計算比按需計算更加穩定,而按需計算在不同情況下會有不同的表現,實際使用中我們可以根據具體的使用場景採用不同的計算策略。

髒值計算

回到我們剛剛講過的圖中:

揭秘你處理資料的“底層邏輯”,詳解公式引擎計算(二)

在這個圖中,如果此時修改了某節點的值,這個時候就需要根據傳播途徑,標記所有需要重算的節點。

舉例:修改了E的內容

根據傳播依次將E C B D A標記

刪去未標記的節點

開始計算剩餘的節點

標記完成之後,我們就不再需要關注未標記節點,計算完成。

整個過程如下圖所示:

揭秘你處理資料的“底層邏輯”,詳解公式引擎計算(二)

拓展:關於運算內容幾個問題

已經介紹完計算鏈的全部內容,為了幫助大家更好地理解,這裡有幾個思考問題:

示例中的圖計算,可否可改用按需計算?

可不可以先計算E的值,再標記並重算C B D A?

根據傳播途徑標記需要重算節點的優勢?

解答部分:

該圖可以進行按需計算,因為按需計算和圖計算都可以對圖內容進行正確計算。

該圖中不可以先算E,然後重標CBDA,因為一旦我們一但先計算E,此時C依舊依賴E的內容,而C又不能先於E計算,這時ABCD節點數值都會變得不可靠,這個計算引用鏈就會被完全破壞。

髒資料的處理中只對傳播路徑上的節點進行處理,在實際應用場景下,幾百個單元格資料處理使,可以大大減少運算的內容。

總結

所有的單元格計算內容就全部為大家介紹完畢了,我們一起回顧一下本章節內容:計算鏈就是將一個個單元格計算串聯起來,分為普通計算和迭代計算。而這裡我們介紹了兩種不同的計算方式——圖計算和按需計算,在面對不同情需要選擇採用不同的計算策略。計算鏈在整個計算過程中不像單元格的計算那麼明顯,但是卻比單元格的計算更加複雜。

在瞭解了計算公式如何進行詞法、語法分析對公式進行快速運算,計算鏈是如何進行多單元格大資料量的處理,接下來將繼續為大家介紹非同步函式在前後算計算中的花式用法。

揭秘你處理資料的“底層邏輯”,詳解公式引擎計算(二)

看到這裡了點個關注吧~後續本葡萄也會為大家帶來更多嚴肅或有趣的內容。

如果想了解更多相關內容,歡迎關注微訊號“葡萄城社群”。