動態地生成用戶輸入的函數表達式(C#)
我在一篇隨筆“畫函數圖形的C#程序,兼論一個病態函數”中提到:
“空間/IV”在該隨筆的評論中指出:
經研究,我寫了一個動態地生成用戶輸入的函數表達式的類(class Expression),表達式使用 C# 語法,可帶一個的自變量(x),其自變量和值均為“double”類型。下面是測試程序的運行結果:
其中最後一個例子就是我在隨筆“畫函數圖形的C#程序,兼論一個病態函數”的下列函數的計算結果:
可以看出,而這函數在任何基於數值 x = 3.13, 3.14, 3.15, 3.16 的插值法,在 x = 3.1416 處得到的解肯定在 30.44652582187 和 30.6693849404716 之間,但實際的解應該是 30.3662371931734,所以說作者斷言在該處肯定會得到一個錯誤的解。
下面就是源程序:
// ExpressionTest.cs - 動態生成數學表達式並計算其值的測試程序
// 編譯方法: csc ExpressionTest.cs Expression.cs
using System;
using Skyiv.Util;
namespace Skyiv.Test
{
class ExpressionTest
{
static void Main(string [] args)
{
try
{
if (args.Length > 0)
{
Console.WriteLine(f(x): {0}, args[0]);
Expression expression = new Expression(args[0]);
for (int i = 1; i < args.Length; i++)
{
double x = double.Parse(args[i]);
Console.WriteLine(f({0}) = {1}, x, expression.Compute(x));
}
}
else Console.WriteLine(Usage: ExpressionTest expression [ parameters
]);
}
catch (Exception ex)
{
Console.WriteLine(錯誤: + ex.Message);
}
}
}
}
// Expression.cs - 動態生成數學表達式並計算其值
// 表達式使用 C# 語法,可帶一個的自變量(x)。
// 表達式的自變量和值均為(double)類型。
// 使用舉例:
// Expression expression = new Expression(Math.Sin(x));
// Console.WriteLine(expression.Compute(Math.PI / 2));
// expression = new Expression(double u = Math.PI - x; +
// double pi2 = Math.PI * Math.PI; +
// return 3 * x * x + Math.Log(u * u) / pi2 / pi2 + 1;);
// Console.WriteLine(expression.Compute(0));
using System;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Reflection;
using System.Text;
namespace Skyiv.Util
{
sealed class Expression
{
object instance;
MethodInfo method;
public Expression(string expression)
{
if (expression.IndexOf(return) < 0) expression = return + expression + ;;
string className = Expression;
string methodName = Compute;
CompilerParameters p = new CompilerParameters();
p.GenerateInMemory = true;
CompilerResults cr = new CSharpCodeProvider().CompileAssemblyFromSource(p, string.
Format(using System;sealed class {0}{{public double {1}(double x){{{2}}}}},
className, methodName, expression));
if(cr.Errors.Count > 0)
{
string msg = Expression( + expression + ): ;
foreach (CompilerError err in cr.Errors) msg += err.ToString() + ;
throw new Exception(msg);
}
instance = cr.CompiledAssembly.CreateInstance(className);
method = instance.GetType().GetMethod(methodName);
}
public double Compute(double x)
{
return (double)method.Invoke(instance, new object [] { x });
}
}
}
在這裡向 CSDN 論壇的“
LoveCherry(論成敗,人生豪邁;大不了,重頭再來!^_^) ”表示感謝,我的程序就是在他的程序的基礎上發展而來的。