C# 字符串转化为表达式
最近想写一个蒙特卡洛模拟的小程序,想让用户来输入要模拟的表达式,如“x^2+y”,然后程序随机生成x、y的值来进行模拟。现在的问题是,不知道如何处理用户以字符串类型输入的...
最近想写一个蒙特卡洛模拟的小程序,想让用户来输入要模拟的表达式,如“x^2+y”,然后程序随机生成x、y的值来进行模拟。
现在的问题是,不知道如何处理用户以字符串类型输入的这种表达式,求高手指点
比如,读取到String str = “x^2+y”之后,该如何去把随机生成的x、y的数值带到里面的去计算x^2+y
如果这个表达式只用一次的话,那么完全可以按照普通计算机编程的思路来做,也就是把字符串拆开,然后每步一个运算符来计算
但是现在在蒙特卡洛模拟的背景下,表达式要被用成千上万次,所以如果每次都拆字符串的话就很没效率了
感觉现在最有可能实现的方式是,只拆一次字符串,然后把表达式以某种形式储存,以后直接运算而不需要再重新拆。不过也只限于想法而已,不知道该怎么实现 展开
现在的问题是,不知道如何处理用户以字符串类型输入的这种表达式,求高手指点
比如,读取到String str = “x^2+y”之后,该如何去把随机生成的x、y的数值带到里面的去计算x^2+y
如果这个表达式只用一次的话,那么完全可以按照普通计算机编程的思路来做,也就是把字符串拆开,然后每步一个运算符来计算
但是现在在蒙特卡洛模拟的背景下,表达式要被用成千上万次,所以如果每次都拆字符串的话就很没效率了
感觉现在最有可能实现的方式是,只拆一次字符串,然后把表达式以某种形式储存,以后直接运算而不需要再重新拆。不过也只限于想法而已,不知道该怎么实现 展开
2个回答
展开全部
嗯,楼上的同学说的是靠谱的方法。如果你有时间的话应该练习表达式识别等等的有趣实例。
如果实在是图便宜的话呢,可以用C#编译器自带的表达式编译系统来完成:
public double Calculate(string formula, double x, double y)
{
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters parameter = new CompilerParameters();
parameter.ReferencedAssemblies.Add("System.dll");
parameter.GenerateExecutable = false; //<--不生成exe
parameter.GenerateInMemory = true; //<--直接在内存运行
CompilerResults result = provider.CompileAssemblyFromSource(parameter,
GenerateCodeBlocks(formula));
//动态编译(VisualStudio F5的时候也是做这个)
if (result.Errors.Count > 0)
{
MessageBox.Show("error");
}
//编译成功
double calculated = Convert.ToDouble(result.CompiledAssembly.GetType("demo.calculation").GetMethod("dowork").Invoke(null, new object[] { x, y }));
//这里通过反射调
return calculated;
}
string GenerateCodeBlocks(string formula)
{
string code =
"using System;" +
"namespace demo" +
"{" +
"public static class calculation" +
"{" +
"public static double dowork(double x, double y)" +
"{ return " + formula +
";}}}"; //这里是将你的formula和代码片段拼接成完整的程序准备编译的过程。
return code;
}
但是注意, x^2这样的表达式是不可以的因为我们要保证这玩意是C#代码,所以你可以通过string处理将p^n处理为Math.Pow(p,n)即可
玩的开心 :)
如果实在是图便宜的话呢,可以用C#编译器自带的表达式编译系统来完成:
public double Calculate(string formula, double x, double y)
{
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters parameter = new CompilerParameters();
parameter.ReferencedAssemblies.Add("System.dll");
parameter.GenerateExecutable = false; //<--不生成exe
parameter.GenerateInMemory = true; //<--直接在内存运行
CompilerResults result = provider.CompileAssemblyFromSource(parameter,
GenerateCodeBlocks(formula));
//动态编译(VisualStudio F5的时候也是做这个)
if (result.Errors.Count > 0)
{
MessageBox.Show("error");
}
//编译成功
double calculated = Convert.ToDouble(result.CompiledAssembly.GetType("demo.calculation").GetMethod("dowork").Invoke(null, new object[] { x, y }));
//这里通过反射调
return calculated;
}
string GenerateCodeBlocks(string formula)
{
string code =
"using System;" +
"namespace demo" +
"{" +
"public static class calculation" +
"{" +
"public static double dowork(double x, double y)" +
"{ return " + formula +
";}}}"; //这里是将你的formula和代码片段拼接成完整的程序准备编译的过程。
return code;
}
但是注意, x^2这样的表达式是不可以的因为我们要保证这玩意是C#代码,所以你可以通过string处理将p^n处理为Math.Pow(p,n)即可
玩的开心 :)
展开全部
我的思路是:先把字符串拆分开,然后判断各个字符代表的含义,再生成相应的表达式来计算。比如case "+" :要执行+的操作 ,依此类推,要注意运算符号执行的顺序。可能要用很多判断。我只是这样想,没有具体实践下,改天有时间了试试,感觉挺有意思 ^_^
-----------------------继续回答楼主的补充------ ^_^
对于你补充的问题,可以这样来分析:
这种可能有点类似于搜索软件的索引文件。我的思路是这样的:软件每次启动时都要加载自己的“记忆文件”(暂时这样叫吧^_^),把自己之前转换过的表达式都记录下来的文件,key=输入的字符串,value=转换后的表达式。具体怎样存储要再做定算。。这样不就提高效率了,用户每次输入字符串先字符串比对,效率要比重新组合表达式高上许多,如果是已经转换过的字符串就返回存储的表达式,否则就重新组合然后存储并返回。
-----------------------继续回答楼主的补充------ ^_^
对于你补充的问题,可以这样来分析:
这种可能有点类似于搜索软件的索引文件。我的思路是这样的:软件每次启动时都要加载自己的“记忆文件”(暂时这样叫吧^_^),把自己之前转换过的表达式都记录下来的文件,key=输入的字符串,value=转换后的表达式。具体怎样存储要再做定算。。这样不就提高效率了,用户每次输入字符串先字符串比对,效率要比重新组合表达式高上许多,如果是已经转换过的字符串就返回存储的表达式,否则就重新组合然后存储并返回。
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询