.NET 4.x Парсинг и вычисление выражения - C#
Формулировка задачи:
Пожалуйста помогите понять, как написать код в компоненте на С# для решения уравнений c одной переменной Методом Ньютона. Не пойму как сделать так, чтобы можно было любую функцию с одной переменной с клавиатуры вводить, и чтобы программа её считывала и находила первую и вторую производные.
Буду очень благодарна за помощь.
Решение задачи: «.NET 4.x Парсинг и вычисление выражения»
textual
Листинг программы
using System;
using System.CodeDom.Compiler;
using System.Reflection;
using System.Windows.Forms;
using Microsoft.CSharp;
namespace WindowsFormsApplication280
{
public partial class Form1 : Form
{
private TextBox tbFunc;
private TextBox tbX;
private TextBox tbResult;
public Form1()
{
InitializeComponent();
tbFunc = new TextBox {Parent = this, Top = 20, Text = "x*x = 1 - x"};
new Label { Parent = this, Top = 5, Text = "Function" };
tbX = new TextBox {Parent = this, Top = 60, Text = "1"};
new Label { Parent = this, Top = 45, Text = "First approximation" };
tbResult = new TextBox { Parent = this, Top = 100, ReadOnly = true };
new Label { Parent = this, Top = 85, Text = "Result" };
new Button { Parent = this, Top = 20, Left = 150, Text = "Calc" }.Click += bt_Click;
}
void bt_Click(object sender, EventArgs e)
{
var calculator = new ExpressionCalculator();
var parts = tbFunc.Text.Split('=');
var expression = string.Format("({0}) - ({1})", parts[0], parts[1]);
calculator.Compile(expression);
var solver = new NewtonSolver();
var res = solver.Solve(x => calculator.Calculate(x), double.Parse(tbX.Text));
tbResult.Text = res.ToString("N5");
}
}
public class ExpressionCalculator
{
private MethodInfo mi;
public void Compile(string expression)
{
string source =
@"
using System;
public static class Calculator
{
public static double Calc(double x)
{
return %expression%;
}
}".Replace("%expression%", expression);
// Настройки компиляции
var compilerParams = new CompilerParameters { GenerateInMemory = true };
// Компиляция
var results = new CSharpCodeProvider().CompileAssemblyFromSource(compilerParams, source);
//обработка ошибок
if (results.Errors.Count > 0)
throw new Exception(results.Errors[0].ErrorText);
//вычисляем
var calculator = results.CompiledAssembly.GetType("Calculator");
mi = calculator.GetMethod("Calc");
}
public double Calculate(double x)
{
return (double)mi.Invoke(null, new object[] { x });
}
}
public class NewtonSolver
{
public double Epsylon = 0.0001d;
public double Solve(Func<double, double> func, double firstApprox)
{
var prev = firstApprox - Epsylon*2;
var x = firstApprox;
while(Math.Abs(x - prev) > Epsylon)
{
prev = x;
//производная
var dx = 0.001d;
var y = func(x);
var dy = func(x + dx) - y;
var deriv = dy/dx;
//формула Ньютона
x = x - y/deriv;
}
return x;
}
}
}