在學習微積分的過程中,我常常會使用 Gemini、 Wolfram Alpha 或 Photomath 等強大的AI、網站、軟體等進行運算。然而,這些工具高度依賴網路連線,在台大這個網路不太好的大學的各種地方,你都有可能連不上這些網站或使用這些app,而我在使用這些工具幫助我解決問題時,也會遇到他們答不出來、回答錯誤或是GUI介面不直觀的問題。因此我想在我的電腦中做一個可以計算微積分的計算機,讓我可以在沒有網路的情況下,也能夠準確地算出我想要的答案。
本專案的目標是開發一款具備圖形化介面(GUI)、完全離線運作的微積分計算機。透過實作堆疊解析與抽象語法樹(AST),程式將能解讀人類輸入的數學算式,並運用「符號運算」進行精確求導。同時,針對數學上缺乏解析解(Closed-form solution)的積分難題,本專案將引入「數值逼近」作為退場機制,確保程式的強健性與實用價值。
圖形化互動介面 (GUI):打造直覺的操作面板,包含數字、變數
算式解析與基礎四則運算:能處理包含括號、加減乘除、次方及基本函數的中序表達式,並正確計算優先級。
符號微分引擎:使用者輸入方程式後,系統能透過內部語法樹的規則替換,精確推導出一階導函數的數學式。
定積分數值運算:針對積分問題,提供數值運算模式。使用者輸入積分上下界後,系統將透過多次走訪求值結合數值分析演算法,計算出精確的定積分面積。
C++。
本專案與現有主流數學工具的對照如下,重點在於解決校園網路環境限制,並提供演算法的透明度與效能分析。
| 比較維度 | 本專案 (C++ 符號微積分引擎) | Wolfram Alpha (專業商用巨頭) | Photomath (行動端解題霸主) | 現代生成式 AI (Gemini, ChatGPT) |
|---|---|---|---|---|
| 核心技術 | C++ AST 解析與模式匹配 | Mathematica 封閉引擎 | OCR 影像辨識 + 專家系統 | 大型語言模型 (LLM) |
| 運算邏輯 | 確定性 (Rule-based) | 確定性 (Rule-based) | 確定性 (Rule-based) | 機率性 (Token Prediction) |
| 底層透明度 | 極高 (完全白盒,可輸出 AST) | 極低 (黑盒子) | 極低 (黑盒子) | 浮動 (取決於是否呼叫外部工具) |
| 運行環境 | 極輕量、本地端離線執行 | 需雲端伺服器集群 | 依賴行動端 App 與網路 | 需龐大的雲端 GPU 算力 |
| 使用限制 (Failure Cases) | 運算極度龐大時受限於本機記憶體限制,且功能受限於已實作完成的。 | 遇極端複雜運算(如1/(x^5+1)的積分時),免費版會強制觸發「超時中斷 (Computation Timeout)」。 | 無法處理複雜的積分問題(如1/(x^5+1)的積分)。 | 若未觸發外部程式碼環境,在多步驟代數推導與複雜運算時極易產生「幻覺 (算錯)」。 |
| 產品定位 | 計算機科學與數學的教育展示 | 專業研究與工程計算 | 國高中生的數學作業輔助 | 泛用型自然語言問答助理 |
算式解析的正確性與強健性驗證點: 測試複雜的巢狀算式(如 (1+(2*(3/(4^5)))))是否能正確轉化為 AST (抽象語法樹)。
驗證方法: 透過後序走訪 (Post-order Traversal) 重新還原算式,確認與輸入值一致。
雙演算法效能基準 (Performance Benchmark)驗證點: 驗證 Shunting-yard 與 Recursive Descent 兩種解析法在處理極長算式時的耗時差異。
驗證方法: 撰寫測試腳本產生
數值積分收斂速度驗證點: 驗證 Simpson’s Rule 是否在更少的迭代次數下,能比 Riemann Sum 達到更高的精確度。
驗證方法: 以已知解析解的函數(如
GUI 與核心引擎的溝通驗證點: 驗證 UI 層輸入的字串能否無縫傳遞給 C++ 運算核心,並在毫秒等級內回傳結果。
驗證方法: 點擊 GUI 按鈕輸入算式,測試顯示介面是否有延遲或字元遺漏。
詞法與語法分析 (Lexer & Parser): 成功實作 Shunting-yard 演算法,能嚴格處理運算子優先級,將人類輸入的複雜中序式 (Infix) 精準轉化為後序式 (Postfix)。
抽象語法樹 (AST) 建構: 摒棄傳統的線性計算,將算式立體化為二元抽象語法樹 (Binary AST),為後續的符號運算打下資料結構基礎。
符號微分引擎 (Symbolic Differentiation Engine): 透過對 AST 進行遞迴走訪與模式匹配 (Pattern Matching),成功實作多項式、指數、對數、三角函數、反三角函數的微分,並能完美展開連鎖律 (Chain Rule) 與乘法/除法法則。
代數化簡模組 (Algebraic Simplification): 開發由下而上 (Bottom-up) 的遞迴化簡器,能自動執行常數摺疊 (Constant Folding,如
面臨挑戰: 當引擎處理複雜算式展開時,字串輸出常伴隨大量括號,大幅降低了數學式的可讀性。原預計透過開發圖形化介面 (GUI) 進行數學符號渲染,但在技術選型上遭遇困難:C++ 缺乏輕量級的原生 UI 支援,而嘗試引入 C# 時,其龐大的框架學習曲線嚴重壓縮了核心邏輯的開發時程。
應對策略: 鑑於本專題的核心評量重點在於「底層資料結構 (AST) 與解析演算法」,前端介面並非當前最優先的技術指標。後續將依據專案進度採取彈性策略:首選方案為導入 Python 相關套件或現成開源 UI 模板進行快速整合 (Rapid Prototyping);若開發時間受限,則會將資源聚焦於強化 C++ 微積分大腦的效能與穩定性。
解析演算法的雙引擎架構 (Dual-Engine Parser):保留現有極速的 Shunting-yard 引擎處理純數學式,並著手開發 Recursive Descent (遞迴下降) 解析器以支援多參數函數 (如 integral(f, a, b))。未來將實作 Dispatcher 切換模式,並量化比較兩種演算法在 AST 建構速度與記憶體消耗上的差異。
積分功能實作 (Integration):
第一階段 (數值積分): 開發 AST 的數值代入求值函數 (Evaluate),結合黎曼和 (Riemann Sum) 演算法計算定積分面積。
第二階段 (符號積分): 嘗試在 AST 上實作基礎的積分模式匹配,讓引擎具備尋找反導數 (Antiderivative) 及輸出積分公式的能力。
Stack (堆疊) 的應用: 在 Shunting-yard 演算法中,嚴格運用 Stack 管理運算子的優先級與括號配對,完美實作中序式至後序式的轉換。
Tree (樹狀資料結構) 的建構與走訪: 專案核心深度依賴二元樹 (Binary Tree) 的資料結構。無論是微分公式的展開、常數的遞迴摺疊,或是算式的字串轉譯,皆大量應用了後序走訪 (Post-order Traversal) 與遞迴 (Recursion) 思維,展現了 Divide and Conquer (分治法) 在處理龐大數學式時的威力。
雜湊表與快速查詢 (Hash Tables & Fast Lookup): 專案中整合了雜湊表(std::unordered_map),將數學運算符號映射至其對應的優先級,並將函數字串(如 sin、ln)與內部列舉型別進行關聯。這確保了
本專案是利用 C++ 開發的「符號積分引擎 (Symbolic Integration Engine)」。本系統能對輸入的數學表達式進行解析,並輸出精確的代數微分與積分結果。此專案分成兩種模式:計算機模式與測試模式,計算機模式會解析使用者輸入的算式,將其轉換成抽象語法樹並進行微分與積分運算,最後將結果化簡並轉回一般的中序表達式。測試模式則是以 sec(x)^n * tan(x)^n 的積分為範例,測試同一算式在執行變數變換以及公式降次時的運行時間與遞迴次數的差異,或者是根據不同的 n 值分析 n 的值會如何影響計算機的效能。
下載整個程式碼檔案後並用 VS Code 開啟專案,依序輸入以下兩條指令:g++ -std=c++17 *.cpp -o engine .\engine.exe,編譯完成就會進入到計算機頁面。按1會進入計算機模式,使用者可以輸入任意算式,引擎會計算此算式的微分與積分結果(若無法函數積分則會顯示"引擎判斷此函數無法積分")。按2會進入測試模式,使用者可以檢視sec(x)^3 * tan(x)^3 、sec(x)^11 * tan(x)^11 、 sec(x)^21 * tan(x)^21 在使用不同演算法時,計算積分時所花費的時間以及遞迴次數。
本專案將「進階程式設計」與「資料結構」的理論應用於實務,從零開始建構一個符號微積分引擎。在開發過程中,我將課程學到的資料結構與演算法,實際用來解決數學算式解析與積分運算的效能瓶頸。主要關聯可分為以下三個部分:
一、資料結構的實際應用
堆疊 (Stack): 在詞法解析階段,利用 Stack 實作 Shunting-Yard 演算法,處理運算子優先權與括號,將使用者輸入的中序字串轉換為後序表達式。
二元樹 (Binary Tree): 引擎的核心基礎。將後序表達式建構成抽象語法樹 (AST) 後,所有的微分、積分規則匹配及化簡 (simplify),都是藉由樹的走訪 (Tree Traversal) 搭配遞迴來完成。
紅黑樹 (Red-Black Tree) 與雜湊表 (Hash Table): 處理有理函數的多項式長除法時,使用了 C++ STL 的 std::map (底層為紅黑樹)。利用其自動排序的特性,讓多項式能自動降冪排列,同時解決了稀疏多項式(如 x^100 + 1)浪費陣列空間的問題。此外,在 Lexer 階段使用了 std::unordered_map (Hash Table) 來達到 O(1) 的函數與常數名稱查找。
二、指標管理與遞迴設計
動態記憶體管理: AST 的變形與展開會頻繁地建立與刪除節點。專案中實作了嚴謹的 copyTree (深拷貝) 與 deleteTree 機制,確保在處理複雜算式時不會發生記憶體洩漏 (Memory Leak)。
遞迴 (Recursion): 除了樹的走訪,專案也將數學上的「分部積分法」實作為遞迴降次函數 (Reduction Formulas)。這不僅簡化了程式碼邏輯,也直接將數學歸納法的概念轉化為程式碼。
三、演算法複雜度與效能分析 (Big O)
專案內建了 Benchmark 測試模式,實際驗證了不同演算法在時間與空間複雜度上的差異。
以 sec(x)^n * tan(x)^n 的積分為例,測試數據顯示,若使用基礎的「變數變換法」(涉及多項式展開),時間複雜度會呈現指數成長 O(2^n),在 n=21 時會產生嚴重的效能瓶頸與記憶體消耗;而改用「遞迴降次法」後,時間複雜度成功降至線性 O(n)。這部分的實作與測試,具體印證了演算法選擇對程式效能的決定性影響。