iloczynem skalarnym \(\displaystyle{ \left\langle p,q\right\rangle = \int_{-1}^{1}p\left( x\right)q\left(x \right)\frac{1}{ \sqrt{1-x^2} }\mbox{d}x }\)
Ten iloczyn skalarny można rozpisać w następujący sposób
Niech \(\displaystyle{ p\left( x\right)q\left( x\right)= \sum_{k=0}^{m+n}a_{k}x^{k}}\)
wówczas \(\displaystyle{ \left\langle p\left( x\right),q\left( x\right) \right\rangle = \sum_{k=0}^{\lfloor\frac{m+n}{2}\rfloor}a_{2k} \cdot \frac{1}{2^{2k}} \cdot {2k \choose k} \cdot \pi }\)
Napisałem nawet program w C# ale użyłem w nim ortogonalizacji Grama - Schmidta
Kod: Zaznacz cały
using System;
using System.Globalization;
namespace NamespaceName
{
public class ClassName
{
public static void Main(string[] args)
{
int n;
double[,] Q;
double sum;
char esc;
do
{
Console.WriteLine("Podaj stopień macierzy");
int.TryParse(Console.ReadLine(),out n);
Q = new double[n+1,n+1];
ModifiedGramSchmidt(n,Q);
for(int i=0;i<=n;i++)
{
sum = 0;
for(int j=0; j<=n;j++)
sum += Q[j,i];
for(int j=0; j<=n;j++)
Q[j,i] /= (double)sum;
}
PrintMatrix(Q);
esc = (char)Console.ReadKey().Key;
}
while(esc != (char)ConsoleKey.Escape);
}
public static void PrintMatrix(double[,] A)
{
NumberFormatInfo nfi = new NumberFormatInfo();
nfi.NumberDecimalDigits = 12;
nfi.NumberGroupSeparator = "";
for(int i=0;i<A.GetLength(0);i++)
{
for(int j=0;j<A.GetLength(1);j++)
{
Console.Write("{0} , ",A[i,j].ToString("N",nfi));
}
Console.WriteLine();
}
Console.WriteLine();
}
public static double InnerProduct(int m, int n,double[] P,double[] Q)
{
double sum = 0.0;
double prod = 1.0;
double[] C = new double[n + m + 1];
Array.Clear(C,0,C.Length);
for(int i = 0;i <= m;i++)
{
for(int j = 0; j <= n;j++)
{
C[i + j] += P[i]*Q[j];
}
}
for(int k = 0;k <= m + n;k += 2)
{
sum += C[k] * prod;
prod *= (double)(k + 1)/(k + 2);
}
return sum * Math.PI;
}
public static double[] GetColumn(double[,] A,int j)
{
double[] temp = new double[A.GetLength(1)];
for(int k = 0;k < A.GetLength(1);k++)
{
temp[k] = A[k,j];
}
return temp;
}
public static void ModifiedGramSchmidt(int n, double[,] Q)
{
/*
for j = 1:n
v_{j} = x_{j};
end for
for j = 1:n
q_{j} = v_{j} / ||v_{j}||_{2}
for k = j + 1:n
v_{k} = v_{k} - (q_{j}^{T}v_{k})*q_{j}
end for
end for
*/
double[,] V = new double[n + 1,n + 1];
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
V[i,j] = (i==j?1:0);
for(int j = 0;j <= n;j++)
{
double invnorm = 1.0/Math.Sqrt(InnerProduct(j,j,GetColumn(V,j),GetColumn(V,j)));
for(int i=j;i>=0;i--)
Q[i,j] = invnorm*V[i,j];
for(int k = j+1;k <= n;k++)
{
double w = InnerProduct(j,k,GetColumn(Q,j),GetColumn(V,k));
for(int i = k;i >= 0;i--)
{
V[i,k] -= w*Q[i,j] ;
}
}
}
}
}
}
tylko jak efektywnie mnożyć macierz przez macierze odbić Householdera ?
Można by też napisać klasę liczb wymiernych na bazie BigInteger z System.Numerics
a także zmodyfikować ten iloczyn skalarny i wtedy pozbyć się problemów z dokładnością