Advertisement
yahorrr

Untitled

Oct 23rd, 2022
1,096
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 18.55 KB | None | 0 0
  1. using System;
  2. using System.Globalization;
  3. using System.Text;
  4.  
  5. namespace PolynomialTask
  6. {
  7.     /// <summary>
  8.     /// Represents a polynomial of integer degree n (in one variable, with real coefficients) - a[n] * x^n + a[n-1] * x^(n-1) + a[n-2] * x^(n-2) +...+ a[1] * x + a[0].
  9.     /// <see cref="http://www.berkeleycitycollege.edu/wp/wjeh/files/2015/01/algebra_note_polynomial.pdf"/>
  10.     /// Implements <see cref="ICloneable"/> and <see cref="IEquatable{T}"/> interfaces.
  11.     /// </summary>
  12.     public sealed class Polynomial : IEquatable<Polynomial>, ICloneable
  13.     {
  14.         /// <summary>
  15.         ///  Internal structure for storing coefficients of polynomial.
  16.         /// </summary>
  17.         private readonly double[] coefficients;
  18.  
  19.         /// <summary>
  20.         /// Initializes static members of the <see cref="Polynomial"/> class.
  21.         /// Set the default value of the accuracy of equality comparing two real numbers to double.Epsilon.
  22.         /// </summary>
  23.         static Polynomial()
  24.         {
  25.             AppSettings = new AppSettings { Epsilon = double.Epsilon, };
  26.         }
  27.  
  28.         /// <summary>
  29.         /// Initializes a new instance of the <see cref="Polynomial"/> class.
  30.         /// </summary>
  31.         /// <param name="coefficients">Coefficients of polynomial according rule coefficients[0] -> a[0], coefficients[1] -> a[1], ..., coefficients[n] -> a[n].
  32.         /// </param>
  33.         /// <exception cref="ArgumentNullException">Thrown when array of coefficients is null.</exception>
  34.         /// <exception cref="ArgumentException">Thrown when array of coefficients is empty.</exception>
  35.         /// <example>
  36.         /// 0.16*x^5+0.05*x^4+0.004*x^3+3.313*x^2+0.2*x-1 -> { -1, 0.2, 3.313, 0.004, 0.05, 0.16 };
  37.         /// 3.3*x^2+2.001*x+1.21394 -> { 1.21394, 2.001, 3.3 }.
  38.         /// </example>
  39.         public Polynomial(params double[]? coefficients)
  40.         {
  41.             if (coefficients == null)
  42.             {
  43.                 throw new ArgumentNullException(nameof(coefficients), "Array of coefficients is null.");
  44.             }
  45.  
  46.             if (coefficients.Length == 0)
  47.             {
  48.                 throw new ArgumentException("Array of coefficients is empty.", nameof(coefficients));
  49.             }
  50.  
  51.             this.Degree = coefficients.Length - 1;
  52.  
  53.             this.coefficients = new double[coefficients.Length];
  54.             Array.Copy(coefficients, this.coefficients, coefficients.Length);
  55.         }
  56.  
  57.         /// <summary>
  58.         /// Gets the AppSettings value.
  59.         /// <see cref="AppSettings"/> class.
  60.         /// </summary>
  61.         public static AppSettings AppSettings { get; }
  62.  
  63.         /// <summary>
  64.         /// Gets the degree value.
  65.         /// </summary>
  66.         /// <example>
  67.         /// The degree of polynomial 3.3*x^2+2.001*x+1.21394 is equal 2;
  68.         /// The degree of polynomial 0.16*x^5+0.05*x^4+0.004*x^3+3.313*x^2+0.2*x-1 is equal 5.
  69.         /// </example>
  70.         public int Degree { get; }
  71.  
  72.         /// <summary>
  73.         /// Returns polynomial coefficient at degree `index`.
  74.         /// </summary>
  75.         /// <param name="index">The zero-based index of the coefficient to get.</param>
  76.         /// <returns>The polynomial coefficient associated with the specified index.</returns>
  77.         /// <exception cref="ArgumentOutOfRangeException">Index is not a valid.</exception>
  78.         /// <example>
  79.         /// For polynomial 3.3*x^2+2.001*x+1.21394 at degree 1 returns 2.001;
  80.         /// For polynomial 0.16*x^5+0.05*x^4+0.004*x^3+3.313*x^2+0.2*x-1 at degree 2 returns 3.313.
  81.         /// For polynomial 0.16*x^5+0.05*x^4+0.004*x^3+3.313*x^2+0.2*x-1 at degree 4 returns 0.05.
  82.         /// </example>
  83.         public double this[int index]
  84.         {
  85.             get
  86.             {
  87.                 if (index < 0 || index > this.coefficients.Length - 1)
  88.                 {
  89.                     throw new ArgumentOutOfRangeException(nameof(index), "Index is not a valid.");
  90.                 }
  91.  
  92.                 return this.coefficients[index];
  93.             }
  94.  
  95.             private set
  96.             {
  97.                 if (index < 0 || index > this.coefficients.Length - 1)
  98.                 {
  99.                     throw new ArgumentOutOfRangeException(nameof(index), "Index is not a valid.");
  100.                 }
  101.  
  102.                 this.coefficients[index] = value;
  103.             }
  104.         }
  105.  
  106.         /// <summary>
  107.         /// Calculates the sum of two polynomials.
  108.         /// </summary>
  109.         /// <param name="lhs">Left-hand side operand.</param>
  110.         /// <param name="rhs">Right-hand side operand.</param>
  111.         /// <returns>The sum of two polynomials.</returns>
  112.         /// <exception cref="ArgumentNullException">Left-hand side operand or right-hand side operand is null.</exception>
  113.         /// <example>
  114.         /// (3.3*x^2+2.001*x+1.21394) + (0.002*x+0.1) => 3.3*x^2+2.003*x+1.31394;
  115.         /// (0.16*x^5+0.05*x^4+0.004*x^3+3.313*x^2+0.2*x-1) + (-4.4*x^3+3.3*x^2-2.2*x+1.1) => 0.16*x^5+0.05*x^4-4.396*x^3+6.613*x^2-2*x+0.1.
  116.         /// </example>
  117.         public static Polynomial operator +(Polynomial? lhs, Polynomial? rhs) => Add(lhs, rhs);
  118.  
  119.         /// <summary>
  120.         /// Calculates the difference of two polynomials.
  121.         /// </summary>
  122.         /// <param name="lhs">Left-hand side operand.</param>
  123.         /// <param name="rhs">Right-hand side operand.</param>
  124.         /// <returns>The difference of two polynomials.</returns>
  125.         /// <exception cref="ArgumentNullException">Left-hand side operand or right-hand side operand is null.</exception>
  126.         /// <example>
  127.         /// (0.002*x+0.1) - (3.3*x^2+2.001*x+1.21394) = -3.3*x^2-1.999*x-1.11394;
  128.         /// (9*x^5-0.896*x^4+4.879*x^3+3.987*x^2-2.569*x+1.204) - (4*x^3-3*x^2-2*x+1) = 9*x^5-0.896*x^4+0.879*x^3+6.987*x^2-0.569*x+0.204.
  129.         /// </example>
  130.         public static Polynomial operator -(Polynomial? lhs, Polynomial? rhs) => Subtract(lhs, rhs);
  131.  
  132.         /// <summary>
  133.         /// Calculates the product of two polynomials.
  134.         /// </summary>
  135.         /// <param name="lhs">Left-hand side operand.</param>
  136.         /// <param name="rhs">Right-hand side operand.</param>
  137.         /// <returns>The product of two polynomials.</returns>
  138.         /// <exception cref="ArgumentNullException">Left-hand side operand or right-hand side operand is null.</exception>
  139.         /// <example>
  140.         /// (3.3*x^2+2.001*x+1.21394) * (0.002*x+0.1) = 0.0066*x^3+0.334*x^2+0.20253*x+0.12139;
  141.         /// (0.16*x^5+0.05*x^4+0.004*x^3+3.313*x^2+0.2*x-1) * (-4.4*x^3+3.3*x^2-2.2*x+1.1) = -0.704*x^8+0.308*x^7-0.2046*x^6-14.498*x^5+10.0991*x^4-2.2242*x^3-0.0957*x^2+2.42*x-1.1.
  142.         /// </example>
  143.         public static Polynomial operator *(Polynomial? lhs, Polynomial? rhs) => Multiply(lhs, rhs);
  144.  
  145.         /// <summary>
  146.         /// Determines whether polynomials are equal based on the equality of the coefficients at the same degrees.
  147.         /// Use Epsilon value of <see cref="AppSettings"/> class to equality compare coefficients of polynomials.
  148.         /// </summary>
  149.         /// <param name="lhs">Left-hand side operand.</param>
  150.         /// <param name="rhs">Right-hand side operand.</param>
  151.         /// <returns>true if left and right are equal; otherwise, false.</returns>
  152.         /// <example>
  153.         /// 0.5*x+1 = 0.49999999*x+1, if Polynomial.AppSettings.Epsilon = 0.00001;
  154.         /// 5.89*x-10.12300013 = 5.89*x-10.123, if Polynomial.AppSettings.Epsilon = 0.00001;
  155.         /// -0.123 = -0.1230000065, if Polynomial.AppSettings.Epsilon = 0.00001.
  156.         /// -0.123 != -0.123065, if Polynomial.AppSettings.Epsilon = 0.00001.
  157.         /// </example>
  158.         public static bool operator ==(Polynomial? lhs, Polynomial? rhs) => lhs?.Equals(rhs) ?? rhs is null;
  159.  
  160.         /// <summary>
  161.         /// Determines whether polynomials are not equal based on the equality of the coefficients at the same degrees.
  162.         /// Use Epsilon value of <see cref="AppSettings"/> class to equality compare coefficients of polynomials.
  163.         /// </summary>
  164.         /// <param name="lhs">Left-hand side operand.</param>
  165.         /// <param name="rhs">Right-hand side operand.</param>
  166.         /// <returns>true if left and right are not equal; otherwise, false.</returns>
  167.         /// <example>
  168.         /// 0.5*x+1 = 0.49999999*x+1, if Polynomial.AppSettings.Epsilon = 0.00001;
  169.         /// 5.89*x-10.12300013 = 5.89*x-10.123, if Polynomial.AppSettings.Epsilon = 0.00001;
  170.         /// -0.123 = -0.1230000065, if Polynomial.AppSettings.Epsilon = 0.00001.
  171.         /// -0.123 != -0.123065, if Polynomial.AppSettings.Epsilon = 0.00001.
  172.         /// </example>
  173.         public static bool operator !=(Polynomial? lhs, Polynomial? rhs) => !(lhs == rhs);
  174.  
  175.         /// <summary>
  176.         /// Calculates the sum of two polynomials.
  177.         /// </summary>
  178.         /// <param name="lhs">Left-hand side operand.</param>
  179.         /// <param name="rhs">Right-hand side operand polynomial.</param>
  180.         /// <returns>The sum of two polynomials.</returns>
  181.         /// <exception cref="ArgumentNullException">Left-hand side operand or right-hand side operand is null.</exception>
  182.         /// <example>
  183.         /// (3.3*x^2+2.001*x+1.21394) + (0.002*x+0.1) => 3.3*x^2+2.003*x+1.31394;
  184.         /// (0.16*x^5+0.05*x^4+0.004*x^3+3.313*x^2+0.2*x-1) + (-4.4*x^3+3.3*x^2-2.2*x+1.1) => 0.16*x^5+0.05*x^4-4.396*x^3+6.613*x^2-2*x+0.1.
  185.         /// </example>
  186.         public static Polynomial Add(Polynomial? lhs, Polynomial? rhs)
  187.         {
  188.             if (lhs == null)
  189.             {
  190.                 throw new ArgumentNullException(nameof(lhs), "Left-hand side operand is null.");
  191.             }
  192.  
  193.             if (rhs == null)
  194.             {
  195.                 throw new ArgumentNullException(nameof(rhs), "Right-hand side operand is null.");
  196.             }
  197.  
  198.             if (lhs.Degree > rhs.Degree)
  199.             {
  200.                 (rhs, lhs) = (lhs, rhs);
  201.             }
  202.  
  203.             double[] coefficients = new double[rhs.Degree + 1];
  204.  
  205.             for (int i = 0; i < lhs.Degree + 1; i++)
  206.             {
  207.                 coefficients[i] = rhs.coefficients[i] + lhs.coefficients[i];
  208.             }
  209.  
  210.             Array.Copy(rhs.coefficients, lhs.Degree + 1, coefficients, lhs.Degree + 1, rhs.Degree - lhs.Degree);
  211.  
  212.             return new Polynomial(coefficients);
  213.         }
  214.  
  215.         /// <summary>
  216.         /// Calculates the difference of two polynomials.
  217.         /// </summary>
  218.         /// <param name="lhs">Left-hand side operand.</param>
  219.         /// <param name="rhs">Right-hand side operand polynomial.</param>
  220.         /// <returns>The difference of two polynomials.</returns>
  221.         /// <exception cref="ArgumentNullException">Left-hand side operand or right-hand side operand is null.</exception>
  222.         /// <example>
  223.         /// (0.002*x+0.1) - (3.3*x^2+2.001*x+1.21394) = -3.3*x^2-1.999*x-1.11394;
  224.         /// (9*x^5-0.896*x^4+4.879*x^3+3.987*x^2-2.569*x+1.204) - (4*x^3-3*x^2-2*x+1) = 9*x^5-0.896*x^4+0.879*x^3+6.987*x^2-0.569*x+0.204.
  225.         /// </example>
  226.         public static Polynomial Subtract(Polynomial? lhs, Polynomial? rhs)
  227.         {
  228.             if (lhs == null)
  229.             {
  230.                 throw new ArgumentNullException(nameof(lhs), "Left-hand side operand is null.");
  231.             }
  232.  
  233.             if (rhs == null)
  234.             {
  235.                 throw new ArgumentNullException(nameof(rhs), "Right-hand side operand is null.");
  236.             }
  237.  
  238.             double[] coefficients = new double[rhs.Degree + 1];
  239.  
  240.             for (int i = 0; i < Math.Min(lhs.Degree + 1, rhs.Degree + 1); i++)
  241.             {
  242.                 coefficients[i] = rhs.coefficients[i] - lhs.coefficients[i];
  243.             }
  244.  
  245.             if (lhs.Degree < rhs.Degree)
  246.             {
  247.                 for (int i = lhs.Degree + 1; i < rhs.Degree + 1; i++)
  248.                 {
  249.                     coefficients[i] = -rhs.coefficients[i];
  250.                 }
  251.             }
  252.             else
  253.             {
  254.                 Array.Copy(rhs.coefficients, lhs.Degree + 1, coefficients, lhs.Degree + 1, rhs.Degree - lhs.Degree);
  255.             }
  256.  
  257.             return new Polynomial(coefficients);
  258.         }
  259.  
  260.         /// <summary>
  261.         /// Calculates the product of two polynomials.
  262.         /// </summary>
  263.         /// <param name="lhs">Left-hand side operator.</param>
  264.         /// <param name="rhs">Right-hand side operator.</param>
  265.         /// <returns>The product of two polynomials.</returns>
  266.         /// <exception cref="ArgumentNullException">Left-hand side operand or right-hand side operand is null.</exception>
  267.         /// <example>
  268.         /// (3.3*x^2+2.001*x+1.21394) * (0.002*x+0.1) = 0.0066*x^3+0.334*x^2+0.20253*x+0.12139;
  269.         /// (0.16*x^5+0.05*x^4+0.004*x^3+3.313*x^2+0.2*x-1) * (-4.4*x^3+3.3*x^2-2.2*x+1.1) = -0.704*x^8+0.308*x^7-0.2046*x^6-14.498*x^5+10.0991*x^4-2.2242*x^3-0.0957*x^2+2.42*x-1.1.
  270.         /// </example>
  271.         public static Polynomial Multiply(Polynomial? lhs, Polynomial? rhs)
  272.         {
  273.             if (lhs == null)
  274.             {
  275.                 throw new ArgumentNullException(nameof(lhs), "Left-hand side operand is null.");
  276.             }
  277.  
  278.             if (rhs == null)
  279.             {
  280.                 throw new ArgumentNullException(nameof(rhs), "Right-hand side operand is null.");
  281.             }
  282.  
  283.             double[] coefficients = new double[rhs.Degree + lhs.Degree + 1];
  284.  
  285.             for (int i = 0; i < lhs.coefficients.Length; i++)
  286.             {
  287.                 for (int j = 0; j < rhs.coefficients.Length; j++)
  288.                 {
  289.                     coefficients[i + j] += lhs.coefficients[i] * rhs.coefficients[j];
  290.                 }
  291.             }
  292.  
  293.             return new Polynomial(coefficients);
  294.         }
  295.  
  296.         /// <summary>
  297.         /// Determines whether or not polynomials are equal based on the equality of the coefficients at the same degrees.
  298.         /// Use Epsilon value of <see cref="AppSettings"/> class to equality compare coefficients of polynomials.
  299.         /// </summary>
  300.         /// <param name="obj">The object to equality compare.</param>
  301.         /// <returns>true if polynomials are equal; otherwise, false.</returns>
  302.         public override bool Equals(object? obj) => this.Equals(obj as Polynomial);
  303.  
  304.         /// <summary>
  305.         /// Determines whether or not polynomials are equal based on the equality of the coefficients at the same degrees.
  306.         /// Use Epsilon value of <see cref="AppSettings"/> class to equality compare coefficients of polynomials.
  307.         /// </summary>
  308.         /// <param name="other">The polynomial to equality compare.</param>
  309.         /// <returns>true if polynomials are equal; otherwise, false.</returns>
  310.         public bool Equals(Polynomial? other)
  311.         {
  312.             if (other == null)
  313.             {
  314.                 return false;
  315.             }
  316.  
  317.             for (int i = 0; i < other.coefficients.Length; i++)
  318.             {
  319.                 if (Math.Abs(other.coefficients[i] - this.coefficients[i]) > AppSettings.Epsilon)
  320.                 {
  321.                     return false;
  322.                 }
  323.             }
  324.  
  325.             return true;
  326.         }
  327.  
  328.         /// <summary>
  329.         /// Calculates the hash code for this instance.
  330.         /// </summary>
  331.         /// <returns>A 32-bit signed integer hash code.</returns>
  332.         public override int GetHashCode()
  333.         {
  334.             return this.Degree;
  335.         }
  336.  
  337.         /// <summary>
  338.         /// Creates the string representation of current <see cref="Polynomial"/> class instance.
  339.         /// </summary>
  340.         /// <returns>The string representation of the current instance.</returns>
  341.         /// <example>
  342.         /// For polynomial with coefficients { 0.0001, -0.003, 0.31, -0.00731, 0.000402, 0.000300021 } -> "0.000300021*x^5+0.000402*x^4-0.00731*x^3+0.31*x^2-0.003*x+0.0001"
  343.         /// For polynomial with coefficients { -1.1, -0.0000007, -0.0957, -2.2242, 10.0991, -14.498, -0.2046, 0.0000012, -0.704 } -> "-0.704*x^8-0.2046*x^6-14.498*x^5+10.0991*x^4-2.2242*x^3-0.0957*x^2-1.1"
  344.         /// For polynomial with coefficients { -1, 0.2, 3.313, 0.004, 0.05, 0.16 } -> "0.16*x^5+0.05*x^4+0.004*x^3+3.313*x^2+0.2*x-1".
  345.         /// </example>
  346.         public override string ToString()
  347.         {
  348.             StringBuilder result = new StringBuilder();
  349.  
  350.             for (int i = this.Degree; i > 1; i--)
  351.             {
  352.                 if (Math.Abs(this.coefficients[i]) <= AppSettings.Epsilon)
  353.                 {
  354.                     continue;
  355.                 }
  356.  
  357.                 result.Append(this.coefficients[i].ToString("+#;-#", CultureInfo.InvariantCulture)).Append("*x^").Append(i);
  358.             }
  359.  
  360.             if (this.coefficients.Length > 1 && Math.Abs(this.coefficients[1]) > AppSettings.Epsilon)
  361.             {
  362.                 result.Append(this.coefficients[1].ToString("+#;-#", CultureInfo.InvariantCulture)).Append("*x");
  363.             }
  364.  
  365.             if (Math.Abs(this.coefficients[0]) > AppSettings.Epsilon)
  366.             {
  367.                 result.Append(this.coefficients[0].ToString("+#;-#", CultureInfo.InvariantCulture));
  368.             }
  369.  
  370.             return result.ToString();
  371.         }
  372.  
  373.         /// <summary>
  374.         /// Calculates a polynomial value in point x.
  375.         /// </summary>
  376.         /// <param name="x">value of variable.</param>
  377.         /// <returns>Polynomial value in point x.</returns>
  378.         /// <example>
  379.         /// Value of polynomial 1.004*x^2+0.014*x+3 in the point -0.5 is equal 3.244;
  380.         /// Value of polynomial 3.3*x^2+2.001*x+1.21394 in the point 1.5 is equal 11.64044.
  381.         /// </example>
  382.         public double CalculateValue(double x)
  383.         {
  384.             double result = this.coefficients[0];
  385.             double copyX = x;
  386.  
  387.             for (int i = 1; i < this.coefficients.Length; i++)
  388.             {
  389.                 result += this.coefficients[i] * x;
  390.                 x *= copyX;
  391.             }
  392.  
  393.             return result;
  394.         }
  395.  
  396.         /// <summary>
  397.         /// Gets copy of coefficients of the polynomial instance.
  398.         /// </summary>
  399.         /// <returns>Coefficients of the polynomial.</returns>
  400.         public double[] GetCoefficients()
  401.         {
  402.             double[] coefficients = new double[this.coefficients.Length];
  403.  
  404.             Array.Copy(this.coefficients, coefficients, this.coefficients.Length);
  405.  
  406.             return coefficients;
  407.         }
  408.  
  409.         /// <summary>
  410.         /// Creates a shallow copy.
  411.         /// </summary>
  412.         /// <returns>A shallow copy.</returns>
  413.         public Polynomial Clone() => (Polynomial)this.MemberwiseClone();
  414.  
  415.         /// <summary>
  416.         /// Creates a shallow copy.
  417.         /// </summary>
  418.         /// <returns>A shallow copy.</returns>
  419.         object ICloneable.Clone() => this.Clone();
  420.     }
  421. }
  422.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement