65.9K
CodeProject 正在变化。 阅读更多。
Home

.NET 极值数值库的 C# 应用数学

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.23/5 (11投票s)

2010年10月10日

CPOL

4分钟阅读

viewsIcon

51118

一篇描述如何使用和集成 .NET 数值库的文章

引言

在代数中,多项式通常表示为 x 的函数(n 次)并绘制其点以形成曲线路径。曲线图通常意味着连续性;也就是说,构成曲线的每个点都有切线。这意味着在每个点上,都有一个方向的变化。这有时被称为微分系数。由于切线很少是水平的,因此它会有一个斜率。假设我们下载 .NET 极值数值库来引用 DLL。您可以在 http://www.extremeoptimization.com/ 下载此数值数学库。它基本上是一系列 DLL,其中包含大多数类型数值计算的方法和数据成员的类。此库会自行安装在*Program Files* 目录中;因此,在引用适当的 DLL 时,请在解决方案资源管理器中右键单击“引用”按钮。然后转到“浏览”,找到位于 *bin* 子目录中的 DLL。引用选择取决于数值计算的类型。这可以包括从微分方程到向量运算。完成此操作后,我们就可以编写一个程序,提供所需的所有信息,例如查找其根。代码将构建一个多项式,然后执行提供所需相应信息的操作。这是一个多项式:x^4 - 10x^3 + 35x^2 - 50x + 24。请看以下代码

using System;
using Extreme.Mathematics.Curves;
public class Program
 {
   public static void Main(string[] args)
    {
     int index;
     Polynomial polynomial1 = new Polynomial(3);
     polynomial1[3] = 1;
     polynomial1[2] = 1;
     polynomial1[1] = 0;
     polynomial1[0] = -2
     double[] coefficients = new double[] {-2, 0, 1, 1};
     Polynomial polynomial2 = new Polynomial(coefficients);
     double[] roots = new double[] {1, 2, 3, 4};
     Polynomial polynomial3 = Polynomial.FromRoots(roots);
            
     double[] xValues = new double[] {1, 2, 3, 4};
     double[] yValues = new double[] {1, 4, 10, 8};

      Polynomial polynomial4 =  Polynomial.GetInterpolatingPolynomial(xValues, yValues);

      Console.WriteLine("polynomial3 = {0}", polynomial3.ToString());
      Console.WriteLine("polynomial1.Parameters.Count = {0}", 
                polynomial1.Parameters.Count);
      Console.Write("polynomial1 parameters:");
    for(index = 0; index < polynomial1.Parameters.Count; index++)
      Console.Write("{0} ", polynomial1.Parameters[index]);
      Console.WriteLine();
            
      Console.Write("polynomial2 parameters:");
    for(index = 0; index < polynomial2.Parameters.Count; index++)
      Console.Write("{0} ", polynomial2.Parameters[index]);
      Console.WriteLine();
      polynomial2.Parameters[0] = 1;
      polynomial2[0] = 1;
            
      Console.WriteLine("Degree of polynomial3 = {0}", polynomial3.Degree);
            
      Console.WriteLine("polynomial1.ValueAt(2) = {0}", polynomial1.ValueAt(2));
            
      Console.WriteLine("polynomial1.SlopeAt(2) = {0}", polynomial1.SlopeAt(2));
            
      Curve derivative = polynomial1.GetDerivative();
      Console.WriteLine("Slope at 2 (derivative) = {0}", derivative.ValueAt(2));
            
      Console.WriteLine("Type of derivative: {0}",
        derivative.GetType().FullName);
      Console.Write("Derivative parameters: ");
      for(index = 0; index < derivative.Parameters.Count; index++)
      Console.Write("{0} ", derivative.Parameters[index]);
      Console.WriteLine();
            
      Console.WriteLine("Type of derivative for polynomial3: {0}", 
                polynomial3.GetDerivative().GetType().FullName);
            
    Line tangent = polynomial1.TangentAt(2);
    Console.WriteLine("Tangent line at 2:");
    Console.WriteLine("  Y-intercept = {0}", tangent.Parameters[0]);
    Console.WriteLine("  Slope = {0}", tangent.Parameters[1]);

            
    Console.WriteLine("Integral of polynomial1 between 0 and 1 = {0}",
                polynomial1.Integral(0, 1));
               roots = polynomial1.FindRoots();
    Console.WriteLine("Number of roots of polynomial1: {0}",
                roots.Length);
    Console.WriteLine("Value of root 1 = {0}", roots[0]);
        
    roots = polynomial3.FindRoots();
    Console.WriteLine("Number of roots of polynomial3: {0}",
                roots.Length);
    Console.WriteLine("Value of root = {0}", roots[0]);
    Console.WriteLine("Value of root = {0}", roots[1]);
            
    Console.WriteLine("Value of root = {0}", roots[2]);
    Console.WriteLine("Value of root = {0}", roots[3]);
             Console.Write("Press Enter key to exit...");
    Console.ReadLine();
        }
    } 

这是编译的输出。请注意,此代码是在 Visual C# 2010 express 中作为控制台应用程序项目运行的。在运行此代码之前,请右键单击“引用”,转到“浏览”,然后添加 *Extreme.Mathematics.Curves* DLL

polynomial3 = x^4-10x^3+35x^2-50x+24
polynomial1.Parameters.Count = 4
polynomial1 parameters:-2 0 1 1
polynomial2 parameters:-2 0 1 1
Degree of polynomial3 = 4
polynomial1.ValueAt(2) = 10
polynomial1.SlopeAt(2) = 16
Slope at 2 (derivative) = 16
Type of derivative: Extreme.Mathematics.Curves.Quadratic
Derivative parameters: 0 2 3 0
Type of derivative for polynomial3: Extreme.Mathematics.Curves.Polynomial
Tangent line at 2:
  Y-intercept = -22
  Slope = 16
Integral of polynomial1 between 0 and 1 = -1.41666666666667
Number of roots of polynomial1: 1
Value of root 1 = 1
Number of roots of polynomial3: 4
Value of root = 1
Value of root = 2
Value of root = 2.99999999999999
Value of root = 4.00000000000001

在某些类型的工程中,x-y 图将水平轴称为实轴,将垂直轴称为虚轴。i^2 = -1。这是一个使用的虚数,通常用于表示向量路径。复数的一个例子是 a = 2 + 4i。现在如果 b = 1 – 3i,c = -3,d = 1 + 1.73205080756888i,那么我们可以使用这些复数进行运算,以获得它们的三角函数、指数函数、对数函数和双曲函数。请看以下代码

using System;
using Extreme.Mathematics;
public class Program 
{
      public static void Main(string[] args)
      {            
    Console.WriteLine("DoubleComplex.Zero = {0}", DoubleComplex.Zero);
              Console.WriteLine("DoubleComplex.One = {0}", DoubleComplex.One);
    // The imaginary unit is given by DoubleComplex.I:
    Console.WriteLine("DoubleComplex.I = {0}", DoubleComplex.I);
    Console.WriteLine();

    //
    // Construct some complex numbers
    //
    // Real and imaginary parts:
    //   a = 2 + 4i
    DoubleComplex a = new DoubleComplex(2, 4);
    Console.WriteLine("a = {0}", a);
    //   b = 1 - 3i
    DoubleComplex b = new DoubleComplex(1, -3);
    Console.WriteLine("b = {0}", b.ToString());
    // From a real number:
    //   c = -3 + 0i
    DoubleComplex c = new DoubleComplex(-3);
    Console.WriteLine("c = {0}", c.ToString());
    // Polar form:
    //   d = 2 (cos(Pi/3) + i sin(Pi/3))
    DoubleComplex d = DoubleComplex.FromPolar(2, Constants.Pi/3);
    
    Console.WriteLine("d = {0}", d);
               Console.WriteLine();

    //
    // Parts of complex numbers
    //
    Console.WriteLine("Parts of a = {0}:", a);
    Console.WriteLine("Real part of a = {0}", a.Re);
    Console.WriteLine("Imaginary part of a = {0}", a.Im);
    Console.WriteLine("Modulus of a = {0}", a.Modulus);
    Console.WriteLine("Argument of a = {0}", a.Argument);
    Console.WriteLine();

    //
    // Basic arithmetic:
    //
    Console.WriteLine("Basic arithmetic:");
    DoubleComplex e = -a;
    Console.WriteLine("-a = {0}", e);
    e = a + b;
    Console.WriteLine("a + b = {0}", e);
    e = a - b;
    Console.WriteLine("a - b = {0}", e);
    e = a * b;
    Console.WriteLine("a * b = {0}", e);
    e = a / b;
    Console.WriteLine("a / b = {0}", e);
    // The conjugate of a complex number corresponds to
    // the "Conjugate" method:
    e = a.Conjugate();
    Console.WriteLine("Conjugate(a) = ~a = {0}", e);
    Console.WriteLine();

    //
    // Functions of complex numbers
    //
    // Most of these have corresponding static methods 
    // in the System.Math class, but are extended to complex 
    // arguments.
    Console.WriteLine("Functions of complex numbers:");

    // Exponentials and logarithms
    Console.WriteLine("Exponentials and logarithms:");
    e = DoubleComplex.Exp(a);
    Console.WriteLine("Exp(a) = {0}", e);
    e = DoubleComplex.Log(a);
    Console.WriteLine("Log(a) = {0}", e);
    e = DoubleComplex.Log10(a);
    Console.WriteLine("Log10(a) = {0}", e);
    // You can get a point on the unit circle by calling
    // the ExpI method:
    e = DoubleComplex.ExpI(2*Constants.Pi/3);
    Console.WriteLine("ExpI(2*Pi/3) = {0}", e);
    // The RootOfUnity method also returns points on the
    // unit circle. The above is equivalent to the second
    // root of z^6 = 1:
    e = DoubleComplex.RootOfUnity(6, 2);
    Console.WriteLine("RootOfUnity(6, 2) = {0}", e);

    // The Pow method is overloaded for integer, double,
    // and complex argument:
    e = DoubleComplex.Pow(a, 3);
    Console.WriteLine("Pow(a,3) = {0}", e);
    e = DoubleComplex.Pow(a, 1.5);
    Console.WriteLine("Pow(a,1.5) = {0}", e);
    e = DoubleComplex.Pow(a, b);
    Console.WriteLine("Pow(a,b) = {0}", e);

    // Square root
    e = DoubleComplex.Sqrt(a);
    Console.WriteLine("Sqrt(a) = {0}", e);
    // The Sqrt method is overloaded. Here's the square 
    // root of a negative double:
    e = DoubleComplex.Sqrt(-4);
              Console.WriteLine("Sqrt(-4) = {0}", e);
    Console.WriteLine();

    //
    // Trigonometric functions:
    //
    Console.WriteLine("Trigonometric function:");
    e = DoubleComplex.Sin(a);
    Console.WriteLine("Sin(a) = {0}", e);
    e = DoubleComplex.Cos(a);
    Console.WriteLine("Cos(a) = {0}", e);
    e = DoubleComplex.Tan(a);
    Console.WriteLine("Tan(a) = {0}", e);

    // Inverse Trigonometric functions:
    e = DoubleComplex.Asin(a);
    Console.WriteLine("Asin(a) = {0}", e);
    e = DoubleComplex.Acos(a);
    Console.WriteLine("Acos(a) = {0}", e);
    e = DoubleComplex.Atan(a);
    Console.WriteLine("Atan(a) = {0}", e);

    // Asin and Acos have overloads with real argument
    // not restricted to [-1,1]:
    e = DoubleComplex.Asin(2);
    Console.WriteLine("Asin(2) = {0}", e);
    e = DoubleComplex.Acos(2);
    Console.WriteLine("Acos(2) = {0}", e);
    Console.WriteLine();
            
    //
            // Hyperbolic and inverse hyperbolic functions:
          //
    Console.WriteLine("Hyperbolic function:");
    e = DoubleComplex.Sinh(a);
    Console.WriteLine("Sinh(a) = {0}", e);
    e = DoubleComplex.Cosh(a);
    Console.WriteLine("Cosh(a) = {0}", e);
    e = DoubleComplex.Tanh(a);
    Console.WriteLine("Tanh(a) = {0}", e);
    e = DoubleComplex.Asinh(a);
    Console.WriteLine("Asinh(a) = {0}", e);
    e = DoubleComplex.Acosh(a);
    Console.WriteLine("Acosh(a) = {0}", e);
    e = DoubleComplex.Atanh(a);
    Console.WriteLine("Atanh(a) = {0}", e);
    Console.WriteLine();

    Console.Write("Press Enter key to exit...");
    Console.ReadLine();
        }
    }

C# 中的 `System.Math` 类中存在类似的 `Math` API,但我们想要一个更深入、更详细的引用库。这是输出

DoubleComplex.Zero = 0
DoubleComplex.One = 1
DoubleComplex.I = 0 + 1i

a = 2 + 4i
b = 1 - 3i
c = -3
d = 1 + 1.73205080756888i

Parts of a = 2 + 4i:
Real part of a = 2
Imaginary part of a = 4
Modulus of a = 4.47213595499958
Argument of a = 1.10714871779409

Basic arithmetic:
-a = -2 - 4i
a + b = 3 + 1i
a - b = 1 + 7i
a * b = 14 - 2i
a / b = -1 + 1i
Conjugate(a) = ~a = 2 - 4i

Functions of complex numbers:
Exponentials and logarithms:
Exp(a) = -4.82980938326939 - 5.59205609364098i
Log(a) = 1.497866136777 + 1.10714871779409i
Log10(a) = 0.650514997831991 + 0.480828578784234i
ExpI(2*Pi/3) = -0.5 + 0.866025403784439i
RootOfUnity(6, 2) = -0.5 + 0.866025403784439i
Pow(a,3) = -88 - 16i
Pow(a,1.5) = -0.849328882115634 + 9.41920164079716i
Pow(a,b) = -120.18477827535 + 30.0306640799618i
Sqrt(a) = 1.79890743994787 + 1.11178594050284i
Sqrt(-4) = 0 + 2i

Trigonometric function:
Sin(a) = 24.8313058489464 - 11.3566127112182i
Cos(a) = -11.3642347064011 - 24.8146514856342i
Tan(a) = -0.000507980623470039 + 1.00043851320205i
Asin(a) = 0.453870209963123 + 2.19857302792094i
Acos(a) = 1.11692611683177 - 2.19857302792094i
Atan(a) = 1.4670482135773 + 0.200586618131234i
Asin(2) = 1.5707963267949 - 1.31695789692482i
Acos(2) = 0 + 1.31695789692482i

Hyperbolic function:
Sinh(a) = -2.370674169352 - 2.84723908684883i
Cosh(a) = -2.45913521391738 - 2.74481700679215i
Tanh(a) = 1.00468231219024 + 0.0364233692474037i
Asinh(a) = 2.18358521656456 + 1.09692154883014i
Acosh(a) = 2.19857302792094 + 1.11692611683177i
Atanh(a) = 0.0964156202029962 + 1.37153510396169i

Press Enter key to exit...

数字 `PI` 通常标记为 `3.14`……等等。然而,`PI` 是一个超越数。将 `PI` 计算到数百万位会得到一串看起来完全没有规律的数字。这常常让数学家们感到困惑。如果我们使用一个通用算法,我们可以将 `PI` 计算到,例如,100 位来验证这一点。另一个例子是 2 的平方根。它通常标记为 1.414。1.414 的倒数是 .707,这在基础电气工程中被称为“平均峰值电流”。这些以及其他例子通常最好通过使用通用算法的计算模型来解决。这是一个例子

using System;
using Extreme.Mathematics.Generic;
using Extreme.Mathematics;
public class GenericAlgorithms
 {
   public static void Main(string[] args)
    {
           
    Console.WriteLine("Computing pi by solving sin(x) == 0 with x0 = 3 using BigFloat:");
           
       Solver<bigfloat> bigFloatSolver = new Solver<bigfloat>();
       // Set the function to solve, and its derivative.
       bigFloatSolver.TargetFunction = 
       delegate(BigFloat x) { return BigFloat.Sin(x); };
       bigFloatSolver.DerivativeOfTargetFunction = 
       delegate(BigFloat x) { return BigFloat.Cos(x); };
       // Now solve to within a tolerance of 10^-100.
       BigFloat pi = bigFloatSolver.Solve(3, BigFloat.Pow(10, -100));
       // Print the results...
       Console.WriteLine("Computed value: {0:F100}", pi);
       // and verify:
       Console.WriteLine("Known value:    {0:F100}", 
       BigFloat.GetPi(AccuracyGoal.Absolute(100)));
       Console.WriteLine();

       // Next, we will use rational numbers to compute
       // an approximation to the square root of 2.
       Console.WriteLine("Computing sqrt(2) by solving x^2 == 2 using BigRational:");
       // Create the solver...
       Solver<bigrational> bigRationalSolver = new Solver<bigrational>();
       // Set properties...
       bigRationalSolver.TargetFunction = 
       delegate(BigRational x) { return x * x - 2; };
       bigRationalSolver.DerivativeOfTargetFunction =
       delegate(BigRational x) { return 2 * x; };
       // Compute the solution...
       BigRational sqrt2 = bigRationalSolver.Solve(1, BigRational.Pow(10, -100));
       // And print the result.
       Console.WriteLine("Rational approximation: {0}", sqrt2);
       // To verify, we convert the BigRational to a BigFloat:
       Console.WriteLine("As real number: {0:F100}", 
       new BigFloat(sqrt2, AccuracyGoal.Absolute(100), RoundingMode.TowardsNearest));
       Console.WriteLine("Known value:    {0:F100}", 
       BigFloat.Sqrt(2, AccuracyGoal.Absolute(100), RoundingMode.TowardsNearest));
       Console.WriteLine();

       // Now, we compute the Lambert W function at x = 3.
       Console.WriteLine("Computing Lambert's W at x = 3
       by solving x*exp(x) == 3 using double solver:");
       // Create the solver...
       Solver<double> doubleSolver = new Solver<double>();
       // Set properties...
       doubleSolver.TargetFunction = delegate(double x) { return x * Math.Exp(x) - 3; };
       doubleSolver.DerivativeOfTargetFunction = 
       delegate(double x) { return Math.Exp(x) * (1 + x); };
       // Compute the solution...
       double W3 = doubleSolver.Solve(1.0, 1e-15);
       // And print the result.
       Console.WriteLine("Solution:    {0}", W3);
       Console.WriteLine("Known value: {0}", 
       Extreme.Mathematics.ElementaryFunctions.LambertW(3.0));

       // Finally, we use generic functions:
       Console.WriteLine("Using generic function delegates:");
      // The delegates are slightly more complicated.
       doubleSolver.TargetFunction = fGeneric<double>;
       doubleSolver.DerivativeOfTargetFunction = dfGeneric<double>;
       double genericW3 = doubleSolver.Solve(1, 1e-15);
       Console.WriteLine("Double:      {0}", genericW3);
       bigFloatSolver.TargetFunction = fGeneric<bigfloat>;
       bigFloatSolver.DerivativeOfTargetFunction = dfGeneric<bigfloat>;
       BigFloat bigW3 = bigFloatSolver.Solve(1, BigFloat.Pow(10, -100));
       Console.WriteLine("BigFloat:    {0:F100}", bigW3);

      Console.Write("Press Enter key to exit...");
      Console.ReadLine();
        }

      // Generic versions of the above
      static T fGeneric<t><T>(T x)
        {
          IRealOperations<t><T> ops =
          (IRealOperations<t><T>)TypeAssociationRegistry.GetInstance(
                    typeof(T), TypeAssociationRegistry.ArithmeticKey);
            return ops.Subtract(
                ops.Multiply(x, ops.Exp(x)),
                ops.FromInt32(3));
        }
        static T dfGeneric<t><T>(T x)
        {
            IRealOperations<t><T> ops =
                (IRealOperations<t><T>)TypeAssociationRegistry.GetInstance(
                    typeof(T), TypeAssociationRegistry.ArithmeticKey);
            return ops.Multiply(
                ops.Exp(x),
                ops.Add(x, ops.One));
        }
    }

    /// <summary>
    /// Class that contains the generic Newton-Raphson algorithm.
    /// </summary>
    /// <typeparam name="T">The operand type.</typeparam>
    class Solver<T><t>
    {
        // Use a static variable to hold the arithmetic instance.
        // We get the instance from the global TypeAssociationRegistry:
        static IFieldOperations<t><T> ops = 
            (IFieldOperations<t><T>)TypeAssociationRegistry.GetInstance(
                typeof(T), TypeAssociationRegistry.ArithmeticKey);

        // Member fields:
        GenericFunction<t><T> f, df;
        int maxIterations = 100;

        // The function to solve:
        public GenericFunction<t><T> TargetFunction
        {
            get { return f; }
            set { f = value; }
        }
        // The derivative of the function to solve.
        public GenericFunction<t><T> DerivativeOfTargetFunction
        {
            get { return df; }
            set { df = value; }
        }
        // The maximum number of iterations.
        public int MaxIterations
        {
            get { return maxIterations; }
            set { maxIterations = value; }
        }

        // The core algorithm.
        // Arithmetic operations are replaced by calls to
        // methods on the arithmetic object (ops).
        public T Solve(T initialGuess, T tolerance)
        {
            int iterations = 0;

            T x = initialGuess;
            T dx = ops.Zero;
            do
            {
                iterations++;
                // Compute the denominator of the correction term.
                T dfx = df(x);
                // Relational operators map to the Compare method.
                // We also use the value of zero for the operand type.
                // if (dfx == 0)
                if (ops.Compare(dfx, ops.Zero) == 0)
                {
                    // Change value by 2x tolerance.
                    // When multiplying by a power of two, it's more efficient 
                    // to use the ScaleByPowerOfTwo method.
                    dx = ops.ScaleByPowerOfTwo(tolerance, 1);
                }
                else
                {
                    // dx = f(x) / df(x)
                    dx = ops.Divide(f(x), dfx);
                }
                // x -= dx;
                x = ops.Subtract(x, dx);
                                
                // if |dx|^2<tolerance>< 0)
                    return x;
            }
            while (iterations < MaxIterations);
            return x;
        }
    }

顺便说一句,这是一个很好的例子,说明 Visual Studio 和 .NET Framework 如何协同工作和集成其他组件以实现所需的结果。大多数刚开始学习托管代码的人都觉得可能会有限制,但事实并非如此。集成 .NET 数值库使我们能够用托管代码编写算法。这是输出

1.JPG

为了扩展 BCL 中定义的 `System.Math` API,请看以下代码

using System; 
 public class Application
  {
   public static void Main()
    {
      Console.WriteLine("Abs({0}) = {1}", -55, Math.Abs(-55));
      Console.WriteLine("Ceiling({0}) = {1}", 55.3, Math.Ceiling(55.3));
      Console.WriteLine("Pow({0},{1}) = {2}", 10.5, 3, Math.Pow(10.5, 3));
      Console.WriteLine("Round({0},{1}) = {2}",
                10.55358, 2, Math.Round(10.55358, 2));
      Console.WriteLine("Sin({0}) = {1}", 323.333, Math.Sin(323.333));
      Console.WriteLine("Cos({0}) = {1}", 323.333, Math.Cos(323.333));
      Console.WriteLine("Tan({0}) = {1}", 323.333, Math.Tan(323.333));
     }
   }

很简单吧?我们只是将一些值代入数学函数并得到结果

Abs(-55) = 55
Ceiling(55.3) = 56
Pow(10.5,3) = 1157.625
Round(10.55358,2) = 10.55
Sin(323.333) = 0.248414709883854
Cos(323.333) = -0.968653772982546
Tan(323.333) = -0.256453561440193

输出结果对于从事数学工作的人员(无论是专业还是教育领域)来说,在非常基础的计算方面很有帮助。但是,当我们能够构建多项式、复数、使用托管代码执行扩展计算时,我们就接近了 FORTRAN、Ada、LISP 等科学计算语言的水平。虽然我们的重点是 C#,但我们将通过 F# 交互界面来研究多项式。因此,我们启动交互界面,设置 DLL 所在的路径,引用 *Extreme.Numerics.Net20.dll*,然后打开对 .NET Framework 的 `System` 命名空间的引用。这是界面视图

2.JPG

这是剩余的代码

open System
 
// The Polynomial class resides in the Extreme.Mathematics.Curves namespace.
open Extreme.Mathematics.Curves
 
// 1st option: a polynomial of a specified degree.
let polynomial1 = new Polynomial(3)
// Now set the coefficients individually. The coefficients
// can be set using the indexer property. The constant term 
// has index 0:
 
polynomial1.Coefficient(3) <- 1.0
polynomial1.Coefficient(2) <- 1.0
polynomial1.Coefficient(1) <- 0.0
polynomial1.Coefficient(0) <- -2.0
 
// 2nd option: specify the coefficients in the constructor
// as an array of doubles:
let coefficients = [| -2.0; 0.0; 1.0; 1.0 |]
let polynomial2 = new Polynomial(coefficients)
 
// In addition; you can create a polynomial that
// has certain roots using the static FromRoots
// method:
let roots = [| 1.0; 2.0; 3.0; 4.0 |]
let polynomial3 = Polynomial.FromRoots(roots)
// Or you can construct the interpolating polynomial
// by calling the static GetInterpolatingPolynomial
// method. The parameters are two double arrays 
// containing the x values and y values respectively.
let xValues = [| 1.0; 2.0; 3.0; 4.0 |]
let yValues = [| 1.0; 4.0; 10.0; 8.0 |]
let polynomial4 = Polynomial.GetInterpolatingPolynomial(xValues, yValues)
 
// The ToString method gives a common string
// representation of the polynomial:
Console.WriteLine("polynomial3 = {0}", polynomial3.ToString())
 
//
// Curve Parameters
//
 
// The shape of any curve is determined by a set of parameters.
// These parameters can be retrieved and set through the
// Parameters collection. The number of parameters for a curve 
// is given by this collection's Count property.
//
// For polynomials, the parameters are the coefficients
// of the polynomial. The constant term has index 0:
Console.WriteLine("polynomial1.Parameters.Count = {0}", polynomial1.Parameters.Count)
// Parameters can easily be retrieved:            
Console.Write("polynomial1 parameters:")
for index = 0 to polynomial1.Parameters.Count - 1 do
  Console.Write("{0} ", polynomial1.Parameters.[index])
done
Console.WriteLine()
// We can see that polynomial2 defines the same polynomial 
// curve as polynomial1:
Console.Write("polynomial2 parameters:")
for index = 0 to polynomial2.Parameters.Count - 1 do
  Console.Write("{0} ", polynomial2.Parameters.[index])
done
Console.WriteLine()
// Parameters can also be set:
polynomial2.Parameters.[0] <- 1.0
 
// For polynomials and other classes that inherit from
// the LinearCombination class, the parameters are also
// available through the indexer property of Polynomial.
// The following is equivalent to the line above:
polynomial2.Coefficient(0) <- 1.0
Console.WriteLine(polynomial2.Coefficient(2))
 
// The degree of the polynomial is returned by
// the Degree property:
Console.WriteLine("Degree of polynomial3 = {0}", 
polynomial3.Degree)
 
//
// Curve Methods
//
 
// The ValueAt method returns the y value of the
// curve at the specified x value:
Console.WriteLine("polynomial1.ValueAt(2) = {0}", polynomial1.ValueAt(2.0))
 
// The SlopeAt method returns the slope of the curve
// a the specified x value:
Console.WriteLine("polynomial1.SlopeAt(2) = {0}", polynomial1.SlopeAt(2.0))
 
// You can also create a new curve that is the 
// derivative of the original:
let derivative = polynomial1.GetDerivative()
Console.WriteLine("Slope at 2 (derivative) = {0}", derivative.ValueAt(2.0))
// For a polynomial, the derivative is a Quadratic curve
// if the degree is equal to three:
Console.WriteLine("Type of derivative: {0}", derivative.GetType().FullName)
Console.Write("Derivative parameters: ")
 
for index = 0 to derivative.Parameters.Count - 1 do
  Console.Write("{0} ", derivative.Parameters.[index])
done
Console.WriteLine()
// If the degree is 4 or higher, the derivative is
// once again a polynomial:
Console.WriteLine("Type of derivative for polynomial3: 
 {0}", polynomial3.GetDerivative().GetType().FullName)
 
// You can get a Line that is the tangent to a curve
// at a specified x value using the TangentAt method:
let tangent = polynomial1.TangentAt(2.0)
Console.WriteLine("Tangent line at 2:")
Console.WriteLine("  Y-intercept = {0}", tangent.Parameters.[0])
Console.WriteLine("  Slope = {0}", tangent.Parameters.[1])
 
// For many curves, you can evaluate a definite
// integral exactly:
Console.WriteLine("Integral of polynomial1
 between 0 and 1 = {0}", polynomial1.Integral(0.0, 1.0))
 
// You can find the zeroes or roots of the curve
// by calling the FindRoots method. Note that this
// method only returns the real roots.
roots = polynomial1.FindRoots()
Console.WriteLine("Number of roots of polynomial1: 
{0}", roots.Length)
Console.WriteLine("Value of root 1 = {0}", roots.[0])
// Let's find polynomial3's roots again:
roots = polynomial3.FindRoots()
Console.WriteLine("Number of roots of polynomial3: 
{0}", roots.Length)
Console.WriteLine("Value of root = {0}", roots.[0])
Console.WriteLine("Value of root = {0}", roots.[1])
// Root finding isn't an exact science. Note the 
// round-off error in these values:
Console.WriteLine("Value of root = {0}", roots.[2])
Console.WriteLine("Value of root = {0}", roots.[3])
  
Console.Write("Press Enter key to exit...")
Console.ReadLine()

输出如下

3.JPG

如果您熟悉 F#,那么在完成时按下回车键,您就会认识到类型推断

val polynomial1 : Extreme.Mathematics.Curves.Polynomial = x^3+x^2-2
val coefficients : float [] = [|-2.0; 0.0; 1.0; 1.0|]
val polynomial2 : Extreme.Mathematics.Curves.Polynomial = x^3+x^2+1
val roots : float [] = [|1.0; 2.0; 3.0; 4.0|]
val polynomial3 : Extreme.Mathematics.Curves.Polynomial =
  x^4-10x^3+35x^2-50x+24
val xValues : float [] = [|1.0; 2.0; 3.0; 4.0|]
val yValues : float [] = [|1.0; 4.0; 10.0; 8.0|]
val polynomial4 : Extreme.Mathematics.Curves.Polynomial =
  -1.83333333333333x^3+12.5x^2-21.6666666666667x+12
val derivative : Extreme.Mathematics.Curves.Curve = 3x^2+2x
val tangent : Extreme.Mathematics.Curves.Line = 16x-22

数学学生和专业人士经常面临的最艰巨的任务之一是编写一个方程,当输入值时,该方程将产生数学问题的解决方案(或估计)。

© . All rights reserved.