using System.Collections.Generic;
using org.mariuszgromada.math.mxparser;
static void Main(string[] args)
TestComplexCalculation();
public static void TestAggregateMethod()
var arrayValue1 = new[] { 1d, 5 };
var arrayValue2 = new[] { 3.5d, 2.1 };
var expression = new Expression("add(B15_1_1,B15_1_2)");
expression = new Expression(expression.getExpressionString().Replace("B15_1_1", string.Join(",", arrayValue1)).Replace("B15_1_2", string.Join(",", arrayValue2)));
var result = expression.calculate();
Console.WriteLine($"汇总:{expression.getExpressionString()} = {result}");
expression = new Expression("mean(B15_1_1,B15_1_2)");
expression = new Expression(expression.getExpressionString().Replace("B15_1_1", string.Join(",", arrayValue1)).Replace("B15_1_2", string.Join(",", arrayValue2)));
result = expression.calculate();
Console.WriteLine($"平均值:{expression.getExpressionString()} = {result}");
expression = new Expression("max(B15_1_1,B15_1_2)");
expression = new Expression(expression.getExpressionString().Replace("B15_1_1", string.Join(",", arrayValue1)).Replace("B15_1_2", string.Join(",", arrayValue2)));
result = expression.calculate();
Console.WriteLine($"最大值:{expression.getExpressionString()} = {result}");
expression = new Expression("min(B15_1_1,B15_1_2)");
expression = new Expression(expression.getExpressionString().Replace("B15_1_1", string.Join(",", arrayValue1)).Replace("B15_1_2", string.Join(",", arrayValue2)));
result = expression.calculate();
Console.WriteLine($"最小值:{expression.getExpressionString()} = {result}");
public static void TestLogicalExpression()
var argument = new Argument("B15_1", 1);
var expression = new Expression("1&&B15_1", argument);
var result = expression.calculate();
Console.WriteLine($"且:{expression.getExpressionString()} = {result}");
expression = new Expression("B15_1||0", argument);
result = expression.calculate();
Console.WriteLine($"或:{expression.getExpressionString()} = {result}");
expression = new Expression("B15_1==1", argument);
result = expression.calculate();
Console.WriteLine($"等于:{expression.getExpressionString()} = {result}");
expression = new Expression("B15_1!=1", argument);
result = expression.calculate();
Console.WriteLine($"不等于:{expression.getExpressionString()} = {result}");
expression = new Expression("B15_1<1", argument);
result = expression.calculate();
Console.WriteLine($"小于:{expression.getExpressionString()} = {result}");
expression = new Expression("B15_1>=1", argument);
result = expression.calculate();
Console.WriteLine($"大于等于:{expression.getExpressionString()} = {result}");
public static void TestComplexCalculation()
var today = new Constant("today", DateTime.Today.GetUnixTimestamp());
var values1 = new[] { 1d, 2, 3 };
var values2 = new[] { 5d };
var expression = new Expression("if(add(B15_2_1)>0,add(B15_2_1),B15_1)");
expression = new Expression(expression.getExpressionString().Replace("B15_2_1", string.Join(",", values1)).Replace("B15_1", string.Join(",", values2)));
var result = expression.calculate();
Console.WriteLine($"示例1:{expression.getExpressionString()} = {result}");
expression = new Expression("(1-(today-B15_2_1)/(B15_2_2-B15_2_1))*4567");
expression.addArguments(new Argument("B15_2_1", DateTime.Parse("2019-01-25").GetUnixTimestamp()));
expression.addArguments(new Argument("B15_2_2", DateTime.Parse("2022-09-30").GetUnixTimestamp()));
expression.addConstants(today);
result = expression.calculate();
Console.WriteLine($"房租:{expression.getExpressionString()} = {result}");
expression = new Expression("if((B15_3_1*5% - B15_3_1*95%/96*(today-B15_2_1)*[s]/[day]/30)<0, B15_3_1*95%/96*(today-B15_2_1)*[s]/[day]/30, B15_3_1*5%)");
expression.addArguments(new Argument("B15_3_1", 250000));
expression.addArguments(new Argument("B15_2_1", DateTime.Parse("2019-05-10").GetUnixTimestamp()));
expression.addConstants(today);
result = expression.calculate();
Console.WriteLine($"车产:{expression.getExpressionString()} = {result}");
var data = new List<Question>
new Question("B15_3_1",5,1),new Question("B15_3_2",8,1),new Question("B15_3_3",10,2),new Question("B15_3_5",3,2)
var function = new Function("income", new CalcIncomeFunction(data.ToArray()));
expression = new Expression("income(B15_3_1,B15_3_2,B15_3_3,B15_3_5)");
expression.addFunctions(function);
expression.addArguments(new Argument("B15_3_1", data.Find(p => p.Code == "B15_3_1").Value));
expression.addArguments(new Argument("B15_3_2", data.Find(p => p.Code == "B15_3_2").Value));
expression.addArguments(new Argument("B15_3_3", data.Find(p => p.Code == "B15_3_3").Value));
expression.addArguments(new Argument("B15_3_5", data.Find(p => p.Code == "B15_3_5").Value));
result = expression.calculate();
Console.WriteLine($"收入:{expression.getExpressionString()} = {result}");
public class CalcIncomeFunction : FunctionExtensionVariadic
private readonly Question[] _questions;
public CalcIncomeFunction(params Question[] questions)
public double calculate(params double[] parameters)
if (_questions == null || _questions.Length == 0)
var median = GetMedian(_questions.Select(p => p.Value));
var data = _questions.Where(p => Math.Abs(p.Value - median) / median < 0.5).ToArray();
var flagCount = data.GroupBy(p => p.Flag).Count();
return data.Where(p => p.Flag == 1).Average(p => p.Value) * 0.8 +
data.Where(p => p.Flag == 2).Average(p => p.Value) * 0.2;
return data.Average(p => p.Value);
public FunctionExtensionVariadic clone()
return new CalcIncomeFunction(_questions);
private static double GetMedian(IEnumerable<double> data)
var ys = data.OrderBy(p => p).ToList();
var mid = (ys.Count - 1) / 2d;
return (ys[(int)mid] + ys[(int)(mid + 0.5)]) / 2D;
public static class DateTimeExtension
public static double GetUnixTimestamp(this DateTime dateTime)
return Math.Floor((dateTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds);
public Question(string code, double value, int? flag)
public string Code { get; set; }
public double Value { get; set; }
public int? Flag { get; set; }