原文链接:https://segmentfault.com/a/1190000003036617
简易使用说明
- 简介
- 操作符
- 值
- 函数
- 参数
简单表达式
- 简介
- 操作符
- 值
- 函数
- 参数
简单表达式
Expression e = new Expression("2 + 3 * 5");
Debug.Assert(17 == e.Evaluate());
计算 .NET 数据类型
计算 .NET 数据类型
Debug.Assert(123456 == new Expression("123456").Evaluate()); // integers
Debug.Assert(new DateTime(2001, 01, 01) == new Expression("#01/01/2001#").Evaluate()); // date and times
Debug.Assert(123.456 == new Expression("123.456").Evaluate()); // floatinpoint numbers
Debug.Assert(true == new Expression("true").Evaluate()); // booleans
Debug.Assert("azerty" == new Expression("'azerty'").Evaluate()); // strings
处理 System.Math 所支持的函数
处理 System.Math 所支持的函数
Debug.Assert(0 == new Expression("Sin(0)").Evaluate());
Debug.Assert(2 == new Expression("Sqrt(4)").Evaluate());
Debug.Assert(0 == new Expression("Tan(0)").Evaluate());
计算自定义函数
计算自定义函数
Expression e = new Expression("SecretOperation(3, 6)");
e.EvaluateFunction += delegate(string name, FunctionArgs args)
{
if (name == "SecretOperation")
args.Result = (int)args.Parameters[0].Evaluate() + (int)args.Parameters[1].Evaluate();
};
Debug.Assert(9 == e.Evaluate());
处理 Unicode 字符
处理 Unicode 字符
Debug.Assert("唐衣可俊" == new Expression("'唐衣可俊'").Evaluate());
Debug.Assert("Hello" == new Expression(@"'u0048u0065u006Cu006Cu006F'"Evaluate());
Debug.Assert("だ" == new Expression(@"'u3060'").Evaluate());
Debug.Assert("u0100" == new Expression(@"'u0100'").Evaluate());
定义参数
定义参数
Expression e = new Expression("Round(Pow([Pi], 2) + Pow([Pi2], 2) + [X], 2)");
e.Parameters["Pi2"] = new Expression("Pi * [Pi]");
e.Parameters["X"] = 10;
e.EvaluateParameter += delegate(string name, ParameterArgs args)
{
if (name == "Pi")
args.Result = 3.14;
};
Debug.Assert(117.07 == e.Evaluate());
简介
NCalc 是一个能够进行表达式计算的一系列程序集( Assembly )。我们主要使用 Expression 类,这个类有一个函数 Evaluate() 能够计算表达式的值。表达式采用字符串形式传入。
举例:
Expression e = new Expression("2 * 3");
object result = e.Evaluate();
NCalc 是一个能够进行表达式计算的一系列程序集( Assembly )。我们主要使用 Expression 类,这个类有一个函数 Evaluate() 能够计算表达式的值。表达式采用字符串形式传入。
举例:
Expression e = new Expression("2 * 3");
object result = e.Evaluate();
Console.WriteLine(result);
很简单,创建一个 Expression 对象,通过构造函数传入需要计算的表达式字符串。调用 Evaluate() 方法进行解析,得到计算结果。
很简单,创建一个 Expression 对象,通过构造函数传入需要计算的表达式字符串。调用 Evaluate() 方法进行解析,得到计算结果。
大小写敏感
NCalc 默认对大小写敏感,如果想要忽略大小写,只需要添加一个参数即可,
Expression e = new Expression("aBs(-1)", EvaluateOptions.IgnoreCase)
Debug.Assert(1M, e.Evaluate());
错误处理
如果表达式有语法错误,求值会抛出 EvaluationException。
try
{
new Expression("(3 + 2").Evaluate();
}
catch(EvaluationException e)
{
Console.WriteLine("Error catched: " + e.Message);
}
当然,我们也可以在求值之前通过 HasErrors() 函数来检测语法错误。
Expression e = new Expression("a + b * (");
if(e.HasErrors())
{
Console.WriteLine(e.Error);
}
表达式缓冲
一个 Expression 对象只会被编译一次。因此通过改变参数来重用表达式对象能够提高程序性能。这样每次计算就只需要遍历表达式树就好了。
实际上,每个编译过的表达式都会缓冲起来,我们完全不需要自己考虑重用表达式。
使用 CacheEnabled 可以从框架层面更改默认设置。
Expression.CacheEnabled = false;
也可以对某个特定的表达式对象进行设置
Expression e = new Expression("1 + 1", EvaluateOption.NoCache);
运算符
毋庸置疑,表达式支持各种基本的运算符。各种运算符的优先级由高到低如下:
原子运算符 (, )
单目运算符 !, not, -, ~(按位取反)
幂次运算符 (原文作者遗漏了,他写了位运算符 &, |, ^(xor), <<, >> )
乘除运算符 *, /, %
加减运算符 +, -
关系运算符 =, ==, !=, <>, <, <=, >, >=
逻辑运算符 or,||,and,&&
注:感觉上面的优先级并不大靠谱,用之前先试试。
毋庸置疑,表达式支持各种基本的运算符。各种运算符的优先级由高到低如下:
原子运算符 (, )
单目运算符 !, not, -, ~(按位取反)
幂次运算符 (原文作者遗漏了,他写了位运算符 &, |, ^(xor), <<, >> )
乘除运算符 *, /, %
加减运算符 +, -
关系运算符 =, ==, !=, <>, <, <=, >, >=
逻辑运算符 or,||,and,&&
注:感觉上面的优先级并不大靠谱,用之前先试试。
值
值是代表具体元素的一个终端口令(A value is a terminal token representing a concrete element),它可以是:
+ 整数(Int32)
+ 浮点数(Decimal)(与 Double 相比,有更高的精度和更小的取值范围)
+ 科学计数(Double)
+ 日期(DateTime)
+ 布尔值(bool)
+ 字符串(String)
+ 函数
+ 参数
整数123
浮点数1.23
值是代表具体元素的一个终端口令(A value is a terminal token representing a concrete element),它可以是:
+ 整数(Int32)
+ 浮点数(Decimal)(与 Double 相比,有更高的精度和更小的取值范围)
+ 科学计数(Double)
+ 日期(DateTime)
+ 布尔值(bool)
+ 字符串(String)
+ 函数
+ 参数
整数123
浮点数1.23
科学计数1.2e5
日期#2017/5/1#
日期用井号包围起来,格式要按照 DateTime 的本地文化(Culture)书写方式写。
布尔值
true
false
字符串
用单引号括起来表示字符串
'hello, tangyikejun!'
函数
跟函数调用的用法差不多
foo(1,'blia')
参数
参考参数部分的说明吧,
日期#2017/5/1#
日期用井号包围起来,格式要按照 DateTime 的本地文化(Culture)书写方式写。
布尔值
true
false
字符串
用单引号括起来表示字符串
'hello, tangyikejun!'
函数
跟函数调用的用法差不多
foo(1,'blia')
参数
参考参数部分的说明吧,
2 + x, 2 + [x]
函数
NCalc 本身已经实现的函数列表如下:
函数名 | 描述 | 用例 | 用例结果 |
---|---|---|---|
Abs | 返回绝对值 | Abs(-1) | 1M |
Acos | 返回余弦值对应的角度 | Acos(1) | 0d |
Asin | - | - | d |
Atan | - | - | d |
Ceiling | 向上取整 | Ceiling(1.5) | 2d |
Cos | - | - | d |
Exp | 相当于 e 的 X 次幂 | Exp(0) | 1d |
Floor | 向下取整 | Floor(1.5) | 1d |
IEEERemainder | IEEE 754 标准下的取余操作,具体细节自行百度 | IEEERemainder(3, 2) | -1d |
Log | 以第二个参数为底取对数 | Log(1,10) | 0d |
Log10 | 以10为底取对数 | Log10(1) | 0d |
Max | - | Max(1,2) | 2 |
Min | - | Min(1,2) | 1 |
Pow | - | Pow(3,2) | 9d |
Round | 第二个参数表示保留几位小数,Round 的舍入规则是“四舍六入五成双”,具体的舍入中间值可以在构造 Expression 对象时用 EvaluateOption.RoundAwayFromZero 设定。 |
Round(3.222,2) | 3.22d |
Sign | 取符号 | Sign(-10) | -1 |
Sin | - | - | d |
Sqrt | 取平方根 | Sqrt(4) | 2d |
Tan | - | - | d |
Truncate | 截取整数部分 | Truncate(1.7) | 1 |
注:结果中的 M 代表 Decimal 类型,d 代表 Double 类型。
其他通用函数:
函数名 | 描述 | 用例 | 结果 |
---|---|---|---|
in | 判断第一个元素是否在后面的一系列值之中 | in(1 + 1, 1, 2, 3) | true |
if | 类似于 expression ? a:b 。根据表达式结果在后两个参数中选择一个返回 | if(3 % 2 = 1, 'value is true', 'value is false') | 'value is true' |