using NCalc;
using System.Text.RegularExpressions;
namespace Alchemy.Core.Extensions
{
public static class NCalcExtensions
{
///
/// 注册自定义函数
///
///
///
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;
}
};
}
///
/// 注册常量
///
///
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,
@"(?