動態地生成用戶輸入的函數表達式(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(論成敗,人生豪邁;大不了,重頭再來!^_^) ”表示感謝,我的程序就是在他的程序的基礎上發展而來的。