| 函數 | 功能 |
HasBracket(str) | 判斷是否含 () |
GetInnermostBracket(str, &start, &end) | 定位最內層括號位置 |
HasFunction(str) | 判斷是否含函數名 |
GetInnermostFunction(str, &fnS,&fnE,&pS,&pE) | 定位最內層函數名與參數括號 [] |
ReplaceRange(str, start, end, replacement) | 區間替換字串 |
EvaluateSimpleArithmetic(str) | 計算無括號無函數的四則運算 |
四則運算計算器(運算子優先級)
double CalcArithmetic(CString expr) {
// 處理優先級:* / 先於 + -
// 掃描策略:左到右,先處理 * /,再處理 + -
// 1. 處理乘除
while (HasMulDiv(expr)) {
int pos = FindFirstMulDiv(expr);
CString left, right;
GetOperands(expr, pos, left, right);
double l = _ttof(left), r = _ttof(right);
double res = (expr[pos]=='*') ? l*r : l/r;
expr = ReplaceOperands(expr, pos, left, right, FormatValue(res));
}
// 2. 處理加減
while (HasAddSub(expr)) {
int pos = FindFirstAddSub(expr);
// 同理計算...
}
return _ttof(expr);
}
變量求值介面
// 單變量掃描
double GetResultFrString1(CString expr, CString varName, double varVal) {
expr.Replace(varName, FormatValue(varVal));
return Evaluate(expr);
}
// 多變量
double GetResultFrStringN(CString expr, CString* vars, double* vals, int n) {
for (int i=0; i
實戰驗證案例
案例 1:任意函數波形繪製(配合 DataShow 類)
函數: 100*pow[2,(sin[X])] —— 注意函數嵌套需加括號 (sin[X])

pow[2, sin[X]] 波形
函數: 100*sign[sin[X]] —— 方波

sign[sin[X]] 方波
函數: 200*sin[X+30]+100*sin[X/2.0] —— 疊加波

多頻率疊加波形
案例 2:科學計算器驗證

計算器運行介面
| 輸入表達式 | 本引擎結果 | MATLAB驗證 | 備註 |
pow[(log[2,3+2]*2*log[2,3+2]*2),0.5] | 4.64386 | 4.6439 | log[2,x] = log2(x) |
1+2+3/4+sin[30]+log[10,100] | 6.25 | 6.2500 | MATLAB用弧度,本引擎用角度 |
6層嵌套 exp[sin[exp[sin[exp[sin[30]]]]]] | 1.0181 | 1.0181 | 極限嵌套正確 |
複雜表達式壓力測試
// 多層括號、函數、運算混合
exp[(56-(((((((sin[(1+29)]+3+2.5)+4)+sin[30]+4.5)+6)+7)+8)+9)-10)]+56-sin[30]+4.5
// 計算結果:62.7183
實現細節與健壯性處理
- 減負數規範化:
2--2 → 2+2,避免解析器誤判
- 步驟記錄:每步化簡寫入
result.txt,step[] 陣列保存最多 100 步供 UI 顯示
- 錯誤碼體系:非法字元、括號不匹配、函數參數數目錯誤、定義域錯誤(如
pow[-1,0.5])
- 無堆疊/鏈表:純
CString 操作(Find/Replace/Mid/Format),邏輯直觀、易維護,雖效能略低於移位歸約法但足夠實用
CExpress 類別介面摘要
class CExpress {
public:
// 核心計算
double GetResultFrString1(CString expr, CString var, double val);
double GetResultFrString2(CString expr, CString v1, double v1, CString v2, double v2);
double GetResultFrStringN(CString expr, CString* vars, double* vals, int n);
// 內部方法
BOOL CheckExpression(CString& expr); // 合法性檢查+預處理
void GetSingleValue(CString str, double& result); // 簡單四則運算
void GetSignFuncVal(CString str, double& result); // 函數計算
void GetBracketResult(CString str, double& result); // 括號遞歸
// 計算過程記錄
CString step[100];
int stepNum;
FILE* resultF; // result.txt
};
總結與擴充方向
- 本引擎以 字串化簡 + 遞歸下降 實現任意表達式計算,代碼清晰、功能完整、驗證通過 MATLAB 對照
- 適用場景:科學計算器、函數繪圖、參數化配置、腳本化業務規則
- 擴充建議:
- 引入 Tokenzier + AST 替代字串替換,大幅提升效能
- 支援使用者自定義函數、陣列/矩陣運算、複數運算
- 整合
muParser、exprtk 等成熟庫替換核心
- 增加編譯期常數摺疊、JIT 代碼生成
作者:莊三少 | 南京航空航天大學能源與動力學院 | Tel: 13512524413 | Email: visualsan@yahoo.cn
配套代碼:含 CExpress 核心類、DataShow 繪圖類、計算器範例、函數繪圖範例
- 上一篇文章: SonicUI引擎:輕量級高效能UI開發框架核心技術深度解析
- 下一篇文章: MFC WinSock ActiveX控件開發實戰(二):高級功能——數據收發、超時控制、VC/VB雙環境調用
Copyright ©
程式碼之家 All Rights Reserved