123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- using NCalc;
- using System.Text.RegularExpressions;
- namespace Alchemy.Core.Extensions
- {
- public static class NCalcExtensions
- {
- /// <summary>
- /// 注册自定义函数
- /// </summary>
- /// <param name="expression"></param>
- /// <exception cref="ArgumentException"></exception>
- public static void AddExtraFunction(this Expression expression)
- {
- expression.EvaluateFunction += (name, args) =>
- {
- object paramX = args.Parameters[0].Evaluate();
- double doubleParamX = paramX.ToString().ToDouble();
- object paramY = null;
- double doubleParamY = 0;
- if (args.Parameters.Count() > 1)
- {
- paramY = args.Parameters[1].Evaluate();
- doubleParamY = paramY.ToString().ToDouble();
- }
- switch (name.ToLower())
- {
- // 阶乘函数
- case "fact":
- int number = paramX.ToString().ToInt();
- args.Result = CalculateFactorial(number);
- break;
- // 反三角函数(返回弧度)
- case "sin":
- args.Result = Math.Sin(paramX.ToString().ToDouble());
- break;
- case "cos":
- args.Result = Math.Cos(paramX.ToString().ToDouble());
- break;
- case "tan":
- args.Result = Math.Tan(paramX.ToString().ToDouble());
- break;
- // 反三角函数(返回弧度)
- case "arcsin":
- case "asin":
- if (doubleParamX < -1 || doubleParamX > 1)
- throw new ArgumentException("反正弦 x∈[-1,1]");
- args.Result = Math.Asin(paramX.ToString().ToDouble());
- break;
- case "arccos":
- case "acos":
- if (doubleParamX < -1 || doubleParamX > 1)
- throw new ArgumentException("反余弦 x∈[-1,1]");
- args.Result = Math.Acos(paramX.ToString().ToDouble());
- break;
- case "arctan":
- case "atan":
- args.Result = Math.Atan(paramX.ToString().ToDouble());
- break;
- // 角度/弧度转换函数
- case "rad": // 角度转弧度
- args.Result = paramX.ToString().ToDouble() * Math.PI / 180;
- break;
- //case "deg": // 弧度转角度
- // args.Result = Convert.ToDouble(param) * 180 / Math.PI;
- // break;
- // 平方根函数
- case "sqrt":
- if (doubleParamX < 0)
- throw new ArgumentException("平方根 x∈[0,+∞)");
- args.Result = Math.Sqrt(doubleParamX);
- break;
- // 次幂函数
- case "pow":
- args.Result = Math.Pow(doubleParamX, doubleParamY);
- break;
- }
- };
- }
- /// <summary>
- /// 注册常量
- /// </summary>
- /// <param name="expression"></param>
- public static void AddExtraConst(this Expression expression)
- {
- expression.Parameters["e"] = Math.E; // 自然常数 e
- expression.Parameters["pi"] = Math.PI; // 圆周率 π
- }
- public static object Evaluate(this string strFormula, string strAngleMode)
- {
- strFormula = Regex.Replace(
- strFormula,
- @"(\d+)\!",
- "fact($1)");
- strFormula = Regex.Replace(
- strFormula,
- @"([^\(\)^]+)\^([^\(\)^]+)",
- "pow($1,$2)");
- if (strAngleMode.Equals("deg"))
- {
- strFormula = Regex.Replace(
- strFormula,
- @"(?<!a)r?(sin|cos|tan)(?![a-z])\(([^)]+)\)",
- "$1(rad($2))");
- }
- strFormula = strFormula.Replace(
- "×",
- "*"
- ).Replace(
- "x",
- "*"
- ).Replace(
- "√",
- "sqrt"
- ).Replace(
- "π",
- "pi"
- ).Replace(
- "%",
- "*0.01"
- );
- Expression expression = new Expression(strFormula);
- expression.AddExtraFunction();
- expression.AddExtraConst();
- string strEvalResult = expression.Evaluate().ToString();
- double doubleResult = strEvalResult.ToDouble();
- double roundedResult = Math.Round(doubleResult, 6);
- return roundedResult;
- }
- private static int CalculateFactorial(int number)
- {
- if (number <= 1) return 1;
- return number * CalculateFactorial(number - 1);
- }
- }
- }
|