mirror of
https://gitee.com/Lamdonn/varch.git
synced 2025-12-07 17:26:43 +08:00
119 lines
3.7 KiB
Markdown
119 lines
3.7 KiB
Markdown
## 介绍
|
|
|
|
这个模块就是一个简单的数学运算表达式的解析计算,通过传入简单的运算表达式,计算出结果。
|
|
|
|
## 接口
|
|
|
|
### 表达式运算
|
|
```c
|
|
double calculate(const char *expression);
|
|
```
|
|
这个函数用法很简单,传入表达式,返回运算结果。默认返回的数据为双精度浮点型,表示的范围会比较广,也适合浮点运算。当计算出错时候,就会返回`NAN`。
|
|
所支持的运算符包括:加法`+`,减法`-`,乘法`*`,除法`/`,次方`^`,取模`%`。运算的优先级有
|
|
| 运算符 | 优先级 |
|
|
|:------:|:-----:|
|
|
| ^ | 0 |
|
|
| * / % | 1 |
|
|
| + - | 2 |
|
|
|
|
除了,基本的运算符运算之外,还支持内置函数的运算。函数名后面跟着`()`,括号内传入函数参数,多个参数就通过逗号`,`隔开。
|
|
| 函数 | 参数 | 描述 |
|
|
|:-----:|:-----:|:------:|
|
|
| abs | 1 | 绝对值 |
|
|
| sqrt | 1 | 开平方 |
|
|
| exp | 1 | 自然指数 |
|
|
| ln | 1 | 自然对数 |
|
|
| sin | 1 | 正弦 |
|
|
| cos | 1 | 余弦 |
|
|
| tan | 1 | 正切 |
|
|
| cot | 1 | 余切 |
|
|
| asin | 1 | 反正弦 |
|
|
| acos | 1 | 反余弦 |
|
|
| atan | 1 | 反正切 |
|
|
| acot | 1 | 反余切 |
|
|
| ceil | 1 | 向上取整 |
|
|
| floor | 1 | 向下取整 |
|
|
| min | 2 | 两者中较小者 |
|
|
| max | 2 | 两者中较大者 |
|
|
| pow | 2 | 次方函数,与`^`一致 |
|
|
| log | 2 | 对数函数 |
|
|
|
|
除外,还有常量,也就是`pi`和`e`,不区分大小写。
|
|
符号和数字之间可以为了简洁美观保留空格,**但数字必须紧密结合成一个数字**。
|
|
|
|
简单的例子:
|
|
```c
|
|
static void test_base(void)
|
|
{
|
|
const char *expression[] = {
|
|
" ( 99 * 3 ) ",
|
|
" min (12, 3)",
|
|
"sin ( 11 / 2 * pi ) + 100 ",
|
|
};
|
|
|
|
for (int i = 0; i < sizeof(expression) / sizeof(expression[0]); i++)
|
|
{
|
|
printf("cal: %s = %lf\r\n", expression[i], calculate(expression[i]));
|
|
}
|
|
}
|
|
```
|
|
运算结果:
|
|
```
|
|
cal: ( 99 * 3 ) = 297.000000
|
|
cal: min (12, 3) = 3.000000
|
|
cal: sin ( 11 / 2 * Pi ) + 100 = 99.000000
|
|
```
|
|
|
|
可以将这个计算模块作为命令导出,以命令形式来计算。这个命令函数,已经将小数点后面没用的`0`去掉,更美观的显示。
|
|
```c
|
|
static int command_calculate(const char *expression)
|
|
{
|
|
double r = NAN;
|
|
if (!expression) return 0;
|
|
r = calculate(expression);
|
|
if (fabs(floor(r) - r) <= DBL_EPSILON && fabs(r) < 1.0e60) printf("%.0lf\r\n", r);
|
|
else if (fabs(r) < 1.0e-6 || fabs(r) > 1.0e9) printf("%e\r\n", r);
|
|
else
|
|
{
|
|
char p[64];
|
|
int len = 0;
|
|
len = sprintf(p, "%lf", r);
|
|
while (len > 0 && p[len-1] == '0' && p[len-2] != '.') {p[--len] = 0;}
|
|
printf("%s\r\n", p);
|
|
}
|
|
return 1;
|
|
}
|
|
```
|
|
输入命令:
|
|
```
|
|
calculate -c "sin( 11 / 2 * Pi ) + 2 ^ 3"
|
|
```
|
|
运算结果:
|
|
```
|
|
7
|
|
```
|
|
|
|
### 导出
|
|
|
|
```c
|
|
int calculate_function(const char *name, double (*func)(), int argc); // 导出函数
|
|
int calculate_constant(const char *name, double value); // 导出常数
|
|
```
|
|
|
|
这两个方法分别导出函数和常熟。
|
|
|
|
导出函数分别传进:函数名,函数指针和函数的参数个数,最大可支持导出 `CALCULATE_EXFUNC_MAX` 个函数。
|
|
|
|
导出常数分别传进:常数名和常数值,最大可支持导出 `CALCULATE_CONSTV_MAX` 个常数。
|
|
|
|
### 列举关键标识
|
|
|
|
```c
|
|
const char* calculate_ls_func(int *argc); // 列举函数
|
|
const char* calculate_ls_const(double *value); // 列举常数
|
|
```
|
|
|
|
这两个方法分别列举函数和常熟。
|
|
|
|
都采用迭代列举方式,直到返回 `NULL` 才列举结束。
|