Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在RPN(反向波兰符号)中使用IF-ELSE?_C#_Math_Rpn - Fatal编程技术网

C# 如何在RPN(反向波兰符号)中使用IF-ELSE?

C# 如何在RPN(反向波兰符号)中使用IF-ELSE?,c#,math,rpn,C#,Math,Rpn,我已经完成了一个RPN类来计算最终用户输入喜欢的字符串 “1.0+3/2-tan(45)/(1+1)+sin(30)*abs(-1)+abs(-10)” 然后,我想解析条件语句和多参数函数,如“if(1>2,3/3,2*1)”,“max(1,2,3,4)” 那么,我的问题是如何在RPN中使用IF-ELSE 这是我的代码:对于如果(1>2,3/3,2*1)您首先从右到左计算三个参数,并将它们的结果推送到堆栈上,使其看起来像这样: top-of-stack->false

我已经完成了一个RPN类来计算最终用户输入喜欢的字符串 “1.0+3/2-tan(45)/(1+1)+sin(30)*abs(-1)+abs(-10)”

然后,我想解析条件语句和多参数函数,如“if(1>2,3/3,2*1)”,“max(1,2,3,4)”

那么,我的问题是如何在RPN中使用IF-ELSE

这是我的代码:

对于
如果(1>2,3/3,2*1)
您首先从右到左计算三个参数,并将它们的结果推送到堆栈上,使其看起来像这样:

top-of-stack->false
              1
              2
然后,
如果
将在RPN引擎中实现(伪代码):

对于多参数函数,不需要特殊处理。只需计算并推送所有参数(通常是从右向左)。函数的实现应该弹出所需数量的参数,然后推送其结果(如果有)。

对于
if(1>2,3/3,2*1)
您应该首先从右到左计算这三个参数,并将其结果推送到堆栈上,使其看起来像这样:

top-of-stack->false
              1
              2
然后,
如果
将在RPN引擎中实现(伪代码):


对于多参数函数,不需要特殊处理。只需计算并推送所有参数(通常是从右向左)。函数的实现应该弹出所需数量的参数,然后推送它的结果(如果有)。

我尝试解析多参数函数,例如if\Max before RPN.parse()

公共类多参数函数解析器
{
public readonly List Funcs=新列表{“IF”,“MAX”};
公共字符串解析(字符串表达式)
{
while(IsFunction(exp,out var index,out var funcName))//
{
var parameters=GetParameters(exp、index、funcName、out-var-before、out-var-after);
var list=GetParameterList(参数);
var值=评估(列表、函数名);
exp=$“{before}({value}){after}”;
}
返回经验;
}
/// 
///Exp是否包含函数?
/// 
/// 
/// 
/// 
/// 
私有bool-IsFunction(字符串exp、out-int索引、out-string-funcName)
{
指数=-1;
funcName=“”;
foreach(Funcs中的var func)
{
var idx=exp.IndexOf($“{func}”(,StringComparison.CurrentCultureIgnoreCase);
如果(idx==-1 | | idx+3>=经验长度-1)
继续;
指数=idx;
funcName=func;
打破
}
返回索引!=-1&&index+3rightCount)
结果+=c;
其他的
打破
索引++;
}
after=exp.Substring(索引+1,exp.Length-index-1);
返回结果;
}
/// 
///解析要列出的参数字符串。
/// 
///最大值(1,-1),1,0
///{“MAX(1,-1)”,“1”,“0”}
私有静态列表GetParameterList(字符串exp)
{
变量计数=扩展长度;
对于(变量i=count-1;i>-1&&exp.Length>0;i--)
{
var c=exp[i];
如果(c!=',')
继续;
var after=exp.Substring(i+1);
var before=exp.Substring(0,i);
如果(在.Count(a=>a='(').Equals(在.Count(a=>a=')))之后)
{
exp=before+'#'+after;
}
}
var results=exp.Split('#').ToList();
返回结果;
}
私有静态双重求值(列表参数、字符串名称)
{
if(funcName.Equals(“MAX”,StringComparison.CurrentCultureIgnoreCase))
返回EvaluateMax(参数);
if(funcName.Equals(“if”,StringComparison.CurrentCultureIgnoreCase))
返回EvaluateIF(参数);
返回0;
}
私有静态双重求值IF(列表参数)
{
if(parameters==null | | parameters.Count!=3)
抛出新异常(“EvaluateIF parameters.Count()!=3”);
var results=新列表();
foreach(参数中的var参数)
{
var rpn=新的rpn();
解析(参数);
var obj=rpn.Evaluate();
if(obj==null)
{
抛出新异常(“EvaluateIF Not Number!”);
}
if(obj.ToString().Equals(“true”,StringComparison.CurrentCultureIgnoreCase))
{
结果:增加(1);
}
else if(obj.ToString().Equals(“false”,StringComparison.CurrentCultureIgnoreCase))
{
结果:添加(-1);
}
其他的
{
if(double.TryParse(obj.ToString(),out var d))
结果:添加(d);
public class MultiParameterFunctionParser
    {
        public readonly List<string> Funcs = new List<string> {"IF", "MAX"};

        public string Parse(string exp)
        {
            while (IsFunction(exp,out var index,out var funcName))//
            {
                var parameters = GetParameters(exp, index, funcName, out var before, out var after);
                var list = GetParameterList(parameters);

                var value = Evaluate(list, funcName);
                exp= $"{before}({value}){after}";
            }

            return exp;
        }

        /// <summary>
        ///  Is Exp Contains a function?
        /// </summary>
        /// <param name="exp"></param>
        /// <param name="index"></param>
        /// <param name="funcName"></param>
        /// <returns></returns>
        private bool IsFunction(string exp, out int index, out string funcName)
        {
            index = -1;
            funcName = "";
            foreach (var func in Funcs)
            {
                var idx = exp.IndexOf($"{func}(", StringComparison.CurrentCultureIgnoreCase);
                if (idx == -1 || idx + 3 >= exp.Length - 1)
                    continue;
                index = idx;
                funcName = func;
                break;
            }

            return index != -1 && index + 3 < exp.Length - 1;
        }

        /// <summary>
        /// Get Parameters' string
        /// </summary>
        /// <param name="exp">8+if(12,sin(90),0)+1.2</param>
        /// <param name="index">2 if's start index</param>
        /// <param name="before">8+</param>
        /// <param name="after">+1.2</param>
        /// <returns>12,sin(90),0</returns>
        private static string GetParameters(string exp,int index, string funcName, out string before, out string after)
        {
            before = exp.Substring(0, index);

            index += funcName.Length + 1;

            var leftCount = 1; // '(' count
            var rightCount = 0;// ')' count
            var results = "";

            while (index < exp.Length && leftCount != rightCount)
            {
                var c = exp[index];
                if (c.Equals('('))
                    leftCount++;
                else if (c.Equals(')'))
                    rightCount++;

                if (leftCount > rightCount)
                    results += c;
                else
                    break;

                index++;
            }

            after = exp.Substring(index + 1, exp.Length - index - 1);

            return results;
        }

        /// <summary>
        /// Parse Parameter string to list. 
        /// </summary>
        /// <param name="exp">MAX(1,-1),1,0</param>
        /// <returns>{"MAX(1,-1)","1","0"}</returns>
        private static List<string> GetParameterList(string exp)
        {
            var count = exp.Length;

            for (var i = count - 1; i > -1 && exp.Length > 0; i--)
            {
                var c = exp[i];
                if (c != ',')
                    continue;

                var after = exp.Substring(i + 1);
                var before = exp.Substring(0,i);

                if (after.Count(a => a == '(').Equals(after.Count(a => a == ')')))
                {
                    exp = before + '#' + after;
                }
            }

            var results = exp.Split('#').ToList();

            return results;
        }

        private static double Evaluate(List<string> parameters, string funcName)
        {
            if (funcName.Equals("MAX", StringComparison.CurrentCultureIgnoreCase))
                return EvaluateMax(parameters);
            if (funcName.Equals("IF", StringComparison.CurrentCultureIgnoreCase))
                return EvaluateIF(parameters);

            return 0;
        }

        private static double EvaluateIF(List<string> parameters)
        {
            if (parameters == null || parameters.Count != 3)
                throw new Exception("EvaluateIF parameters.Count()!=3");

            var results = new List<double>();
            foreach (var parameter in parameters)
            {
                var rpn = new RPN();
                rpn.Parse(parameter);
                var obj = rpn.Evaluate();

                if (obj == null)
                {
                    throw new Exception("EvaluateIF Not Number!");
                }
                if (obj.ToString().Equals("true", StringComparison.CurrentCultureIgnoreCase))
                {
                    results.Add(1);
                }
                else if (obj.ToString().Equals("false", StringComparison.CurrentCultureIgnoreCase))
                {
                    results.Add(-1);
                }
                else
                {
                    if (double.TryParse(obj.ToString(), out var d))
                        results.Add(d);
                    else
                        throw new Exception("EvaluateIF Not Number!");
                }
            }

            return results[0] >= 0 ? results[1] : results[2];
        }

        private static double EvaluateMax(IEnumerable<string> parameters)
        {
            var results = new List<double>();
            foreach (var parameter in parameters)
            {
                var rpn = new RPN();
                rpn.Parse(parameter);
                var obj = rpn.Evaluate();
                if (double.TryParse(obj.ToString(), out var d))
                    results.Add(d);
            }

            return results.Count > 0 ? results.Max() : 0;
        }
    }