Linear Algebra
Colin Fahey
1. Software
LinearAlgebra.zip
Lineær algebra kildekoden (C#)
19910 bytes
MD5: 11d8c8035cac30ba543e5e0b72ee9767
2. Indledning
Denne artikel beskriver, vektorer og matricer i (d)-dimensionelle rum.
3. (d)-dimensionelle rum: Attributter
3.1 Array
"array:" En samling af variabler, sådan at hver variabel har et unikt navn, og sådan, at navne kan blive tildelt en ordre.
Integer værdier kan bruges som navne til variabler i en array.
For eksempel, hvis en række indeholder (d) variabler, så integer værdier { 0, 1, 2, ..., (d-1) } kan være navne tildeles de variabler i array.
3.2 (d)-dimensional vektor
"(d)-dimensional vektor:" En vifte af (d) variabler.
"vektor komponent:" En variabel inden for en vektor.
3.3 (d)-dimensionelle vektorrum
"en-dimensionelle rum:" Det komplette sæt af værdier, der kan gemmes af en variabel.
"(d)-dimensionelle rum:" Det komplette sæt af kombinationer af værdier, der kan gemmes af en vifte af (d) variabler.
Den formelle definition på en "vektor rummet:"
Lad (T) være en grundlæggende type (eksempler: reelt tal, heltal, komplekse tal, rationelt tal, osv.).
Enhver variabel for en grundlæggende type kaldes en "skalar."
En "(T)-typen (d)-dimensional vektorrum" er det sæt (S) af (d)-dimensionelle vektorer have to operationer, vektor Ud (+), og skalar multiplikation (*), der opfylder de betingelser nedenfor:
(1) Hvis (v) og (w) er to vektorer i (S), så (v + w) er også en vektor i (S);
(2) Hvis (u), (v), og (w) er alle tre vektorer i (S), så (u + v) + w = u + (v + w);
[tilsætningsstof kommutativitet]
(3) Hvis (v) og (w) er to vektorer i (S), så (v + w) = (w + v);
[tilsætningsstof Associativitet]
(4) Der er en "nul vektor," (0) i (S), således at der for enhver vektor (v) i (S), (v + (0)) = v;
[tilsætningsstof identitet]
(5) Hvis (c) er enhver skalar af type (T), og (v) er enhver vektor i (S), så produktet (c * v) er en vektor i (S);
(6) Hvis (a), (b), og (c) er nogen scalars af type (T), og (v) og (w) er nogen vektorer i (S), så (a + b) * v = a*v + b*v, og c*(v + w) = c*v + c*w;
[multiplicative distributivity]
(7) Hvis (a) og (b) er nogen scalars af type (T), og (v) er enhver vektor i (S), så (a*b)*v = a*(b*v);
(8) Hvis "1" er en skalar af type (T) sådan, at (1*1)=1, og (v) er enhver vektor i (S), så (1*v) = v;
(9) For hver vektor (v) i (S), vektor (-1)*v = -v opfylder v + (-v) = (0);
[tilsætningsstof inverse]
3.4 (d)-dimensional vektor-kode
Nedenstående kode viser, hvordan en (d)-dimensional vektor, med 64-bit floating-point komponenter, kan gennemføres.
En matrix er tilstrækkeligt til at repræsentere en vektor.
Nedenstående kode har et array i en klasse, kun for bekvemmelighed.
Koden er ikke beregnet til at blive effektiv.
En struktur (eksempel: "struct" en værdi type) repræsenterer vektorer af et fast antal dimensioner (eksempler: 3 eller 4) må forventes at være langt mere effektiv end den generelle (d)-dimensional vektor klasse vist her.
Selv om koden nedenfor definerer en vektor med floating-point komponenter, dette dokument også gør brug af vektorer med heltal komponenter.
Nedenstående kode kan nemt blive ændret for at gennemføre vektorer med heltal komponenter.
using System;
using System.Collections.Generic;
using System.Text;
// Multidimensional vector with 64-bit floating-point components:
public class VectorF64
{
private double[] components;
public int Dimensions()
{
if (null == this.components)
{
return (0);
}
return (this.components.Length);
}
public VectorF64()
{
this.components = null;
}
public VectorF64( params double[] paramValues )
{
this.components = null;
if (null == paramValues)
{
return;
}
int dimensions = paramValues.Length;
this.components = new double[dimensions];
for (int i = 0; i < dimensions; i++)
{
this.components[i] = paramValues[i];
}
}
public VectorF64( VectorF64 other )
{
this.components = null;
if (null == other)
{
return;
}
if (null == other.components)
{
return;
}
int dimensions = other.Dimensions();
this.components = new double[dimensions];
for (int i = 0; i < dimensions; i++)
{
this.components[i] = other.components[i];
}
}
public double this[int index]
{
get
{
if (null == this.components)
{
return (0.0);
}
if
(
(index >= 0)
&& (index < this.components.Length)
)
{
return (this.components[index]);
}
return (0.0);
}
set
{
if (null == this.components)
{
return;
}
if
(
(index >= 0)
&& (index < this.components.Length)
)
{
this.components[index] = value;
}
}
}
public void Write( int precision )
{
if (null == this.components)
{
Log.Write( String.Empty + '(' + ' ' + ')' );
return;
}
int dimensions = this.Dimensions();
if (0 == dimensions)
{
Log.Write( String.Empty + '(' + ' ' + ')' );
return;
}
// Determine the largest component width in characters
// so that we can make all components an equal width.
int largestComponentWidth = 1;
for (int i = 0; i < dimensions; i++)
{
// { index [,minwidth] [:typeCode[precision]] }
// (minwidth<0) means left-justify
String text = String.Format( String.Empty + '{' + '0' + ':'
+ 'g' + precision + '}', this[i] );
if (text.Length > largestComponentWidth)
{
largestComponentWidth = text.Length;
}
}
Log.Write( '(' );
for (int i = 0; i < dimensions; i++)
{
Log.Write( ' ' );
String text =
String.Format( String.Empty + '{' + '0' + ','
+ largestComponentWidth + ':' + 'g' + precision + '}',
this[i] );
Log.Write( text );
if ((i + 1) < dimensions)
{
Log.Write( ',' );
}
else
{
Log.Write( ' ' );
}
}
Log.Write( ')' );
}
public void WriteLine( int precision )
{
this.Write( precision );
Log.WriteLine();
}
public void WriteLine()
{
const int defaultPrecision = 8;
this.Write( defaultPrecision );
Log.WriteLine();
}
// . . .
public static void Test()
{
// A 3-dimensional vector with 64-bit floating-point components:
VectorF64 v3 = new VectorF64( 0.0, 1.0, 2.0 );
v3.WriteLine(); // ( 0, 1, 2 )
// A 4-dimensional vector with 64-bit floating-point components:
VectorF64 v4 = new VectorF64( 0.0, 1.0, 2.0, 3.0 );
v4.WriteLine(); // ( 0, 1, 2, 3 )
// . . .
}
}
"(d)-dimensional nul vektor:" En vektor med alle (d) komponenter er lig med nul.
public class VectorF64
{
// . . .
public static VectorF64 Zero( int dimensions )
{
VectorF64 zero = new VectorF64();
zero.components = new double[dimensions];
for (int i = 0; i < dimensions; i++)
{
zero[i] = 0.0;
}
return (zero);
}
// . . .
public static void Test()
{
// . . .
// An 8-dimensional vector with all 8 64-bit floating-point
// components set to zero:
VectorF64 z = VectorF64.Zero( 8 );
z.WriteLine(); // ( 0, 0, 0, 0, 0, 0, 0, 0 )
// . . .
}
}
3.5 (d)-dimensionelle rum: punkt
"(d)-dimensionelle rum punkt:" En vifte af (d) variabler med særlige værdier "(koordinere værdier)."
"(d)-dimensionelle rum oprindelse:" En vifte af (d) variabler med alle værdier lig med nul.
3.6 (d)-dimensionelle vektorer: ikke-relative og relative
En (d)-dimensional vektor, som er "ikke-relative" er en (d)-dimensional vektor, som direkte repræsenterer en status eller konfiguration.
En (d)-dimensional vektor, der er "relativ" er en (d)-dimensional vektor, der repræsenterer ændringer i et sæt af komponenter.
En relativ vektor kan udgøre forskellen mellem to ikke-relativ vektorer.
Da en relativ vektor, fastsættelse af en ikke-relativ status eller konfiguration benytter denne relative vektor kræver kombinere at den relative vektor med en ikke-relativ vektor.
Ikke-relative vektorer og relative vektorer er begge vektorer.
Hvorvidt en bestemt vektor er ikke-relativ eller relative skal specificeres, hvor vektoren er defineret.
Hvis en (d)-dimensional vektor tolkes som værende ikke-relativ, så (d)-dimensional vektor kan repræsentere et punkt i (d)-dimensionelle rum.
3.7 (d)-dimensional vektor addition, subtraktion, og skalering
Vector addition, subtraktion, og skalering:
public class VectorF64
{
// . . .
public static VectorF64 operator +( VectorF64 a, VectorF64 b )
{
if ((null == a) ¦¦ (null == b))
{
return (new VectorF64()); // Vector not specified.
}
if ((null == a.components) ¦¦ (null == b.components))
{
return (new VectorF64()); // Vector is empty.
}
if (a.Dimensions() != b.Dimensions())
{
return (new VectorF64()); // Vectors not the same size.
}
int dimensions = a.Dimensions();
VectorF64 result = VectorF64.Zero( dimensions );
for (int i = 0; i < dimensions; i++)
{
result[i] = a[i] + b[i];
}
return (result);
}
public static VectorF64 operator -( VectorF64 a, VectorF64 b )
{
if ((null == a) ¦¦ (null == b))
{
return (new VectorF64()); // Vector not specified.
}
if ((null == a.components) ¦¦ (null == b.components))
{
return (new VectorF64()); // Vector is empty.
}
if (a.Dimensions() != b.Dimensions())
{
return (new VectorF64()); // Vectors not the same size.
}
int dimensions = a.Dimensions();
VectorF64 result = VectorF64.Zero( dimensions );
for (int i = 0; i < dimensions; i++)
{
result[i] = a[i] - b[i];
}
return (result);
}
public static VectorF64 operator -( VectorF64 a )
{
if (null == a)
{
return (new VectorF64()); // Vector not specified.
}
if (null == a.components)
{
return (new VectorF64()); // Vector is empty.
}
int dimensions = a.Dimensions();
VectorF64 result = VectorF64.Zero( dimensions );
for (int i = 0; i < dimensions; i++)
{
result[i] = (-( a[i] ));
}
return (result);
}
public static VectorF64 operator *( double scale, VectorF64 a )
{
if (null == a)
{
return (new VectorF64()); // Vector not specified.
}
if (null == a.components)
{
return (new VectorF64()); // Vector is empty.
}
int dimensions = a.Dimensions();
VectorF64 result = VectorF64.Zero( dimensions );
for (int i = 0; i < dimensions; i++)
{
result[i] = scale * a[i];
}
return (result);
}
public static VectorF64 operator *( VectorF64 a, double scale )
{
if (null == a)
{
return (new VectorF64()); // Vector not specified.
}
if (null == a.components)
{
return (new VectorF64()); // Vector is empty.
}
int dimensions = a.Dimensions();
VectorF64 result = VectorF64.Zero( dimensions );
for (int i = 0; i < dimensions; i++)
{
result[i] = scale * a[i];
}
return (result);
}
// . . .
public static void Test()
{
// . . .
// Examples of vector addition, subtraction, and scaling:
VectorF64 a = new VectorF64( 0.0, 1.0, 2.0, 3.0 );
a.WriteLine(); // ( 0, 1, 2, 3 )
VectorF64 b = new VectorF64( 3.0, 2.0, 1.0, 0.0 );
b.WriteLine(); // ( 3, 2, 1, 0 )
VectorF64 c = new VectorF64();
c.WriteLine(); // ( )
c = a + b;
c.WriteLine(); // ( 3, 3, 3, 3 )
c = a - b;
c.WriteLine(); // ( -3, -1, 1, 3 )
c = -b;
c.WriteLine(); // ( -3, -2, -1, 0 )
c = 3.0 * a;
c.WriteLine(); // ( 0, 3, 6, 9 )
// . . .
}
}
3.8 (d)-dimensional grundlag vektorer
Den formelle definition på "grundlag" af et vektorrum:
Lad (T) være en grundlæggende type (eksempler: reelt tal, heltal, komplekse tal, rationelt tal, osv.).
Enhver variabel for en grundlæggende type kaldes en "skalar."
Lad (V) være en "(T)-typen (d)-dimensional vektorrum."
Hvis den ikke-nul vektorer { u1, u2, ..., ud } i (V) er sådan, at enhver vektor (v) i (V) kan skrives som en "lineær kombination" af disse vektorer, v = c1*u1 + c2*u2 + ... + cd*ud, hvor { c1, c2, ..., cd } er scalars af type (T), så (V) er "kalibreret" fra vektorer { u1, u2, ..., ud }.
Et sæt af ikke-nul vektorer { u1, u2, ..., ud } at "span" vektorrum (V) er navngivet på "basis" af (V).
Et simpelt "grundlag" af en (d)-dimensional vektorrum er det sæt af (d) adskiller (d)-dimensionelle vektorer, hver med en komponent svarende til en og alle andre komponenter er lig med nul.
Sådanne grundlag vektorerne er "Orthonormal," hvilket betyder, at de er gensidigt vinkelrette "(retvinklede)," og at hver vektor har enheden længde.
Hver sådan vektor er en enhed vektor parallel til en af de (d) koordinere akserne.
Tilkendegive vilkårlig vektor som en "lineær kombination" af disse grundlag vektorer direkte; hver bestanddel af den vilkårlige vektoren er ganget med den tilsvarende grundlag vektor, og disse produkter er føjet sammen om at danne vilkårlig vektor.
Nedenstående kode viser, hvordan en vektor kan udtrykkes som en "lineær kombination" af basis vektorer.
Nedenstående kode vilkårligt definerer en Orthonormal sæt grundlag vektorer.
public class VectorF64
{
// . . .
public static VectorF64 BasisVector( int dimensions, int componentIndex )
{
if (dimensions < 0)
{
// Invalid number of dimensions specified.
return (new VectorF64());
}
VectorF64 basisVector = VectorF64.Zero( dimensions );
if ((componentIndex >= 0) && (componentIndex < dimensions))
{
basisVector[ componentIndex ] = 1.0;
}
return (basisVector);
}
// . . .
public static void Test()
{
// . . .
// The 4 basis vectors of 4-dimensional space,
// each with 4 64-bit floating-point components:
VectorF64 b0 = VectorF64.BasisVector( 4, 0 );
b0.WriteLine(); // ( 1, 0, 0, 0 )
VectorF64 b1 = VectorF64.BasisVector( 4, 1 );
b1.WriteLine(); // ( 0, 1, 0, 0 )
VectorF64 b2 = VectorF64.BasisVector( 4, 2 );
b2.WriteLine(); // ( 0, 0, 1, 0 )
VectorF64 b3 = VectorF64.BasisVector( 4, 3 );
b3.WriteLine(); // ( 0, 0, 0, 1 )
// . . .
}
}
Enhver vektor i (d)-dimensionelle rum kan udtrykkes som en sum af produkterne af tal og grundlag vektorer:
public class VectorF64
{
// . . .
public static void Test()
{
// . . .
// The following two vectors are equivalent:
// A 4-dimensional vector with 64-bit floating-point components:
VectorF64 va = new VectorF64( 0.1, 1.1, 2.2, 3.3 );
va.WriteLine(); // ( 0.1, 1.1, 2.2, 3.3 )
// A 4-dimensional vector formed by scaling the 4 independent
// basis vectors for 4-dimensional space:
VectorF64 vb =
0.1 * VectorF64.BasisVector( 4, 0 )
+ 1.1 * VectorF64.BasisVector( 4, 1 )
+ 2.2 * VectorF64.BasisVector( 4, 2 )
+ 3.3 * VectorF64.BasisVector( 4, 3 );
vb.WriteLine(); // ( 0.1, 1.1, 2.2, 3.3 )
// . . .
}
}
3.9 (d)-dimensionelle rum: Afstanden mellem punkterne
Lad (P) være en (d)-dimensional vektor, der repræsenterer et punkt i (d)-dimensionelle rum.
Lad (Q) være en (d)-dimensional vektor, der repræsenterer et punkt i (d)-dimensionelle rum.
Lad (R) være en (d)-dimensional vektor, der repræsenterer ændringen i (d) koordinater til at komme fra punkt (P) til punkt (Q); R = (Q - P).
I én-dimensionelle rum, P = ( p0 ), Q = ( q0 ), og R = (Q - P) = ( q0 - p0 ).
Afstanden mellem de to punkter er: Abs( q0 - p0 ).
I to-dimensionelle rum, P = ( p0, p1 ), Q = ( q0, q1 ), og R = (Q - P) = ( q0-p0, q1-p1 ).
Tolkning de to vinkelrette fordrivelser som den vinkelrette sider af en højre-trekant, hvor afstanden mellem de punkter svarer til længden af hypotenusen af denne trekant.
De Pythagorean formel, (a*a) + (b*b) = (c*c), hvor (a) og (b) er længderne af den vinkelrette sider af en højre-trekant, og (c) er længden af hypotenusen (påvirke side), kan bruges til at bestemme afstanden mellem de to punkter: Sqrt( Sq(q0-p0) + Sq(q1-p1) ).
I tre-dimensionelle rum, P = ( p0, p1, p2 ), Q = ( q0, q1, q2 ), og R = (Q - P) = ( q0-p0, q1-p1, q2-p2 ).
Tolke forskydning ( q0-p0, q1-p1, 0 ) som den vinkelrette sider af en højre-trekant og ved at bruge Pythagorean formel, giver afstanden mellem punkt (P) og det punkt ( q0, q1, p2 ): d01 = Sqrt( Sq(q0-p0) + Sq(q1-p1) ).
Denne forskydning ( q0-p0, q1-p1, 0 ) er vinkelret på den forskydning ( 0, 0, q2-p2 ), og en anden højre-trekant kan dannes, og Pythagorean formel kan bruges igen.
Således er afstanden fra punkt (P) til punkt (Q) er givet ved: Sqrt( Sq(d01) + Sq(q2-p2) ) = Sqrt( (Sq(q0-p0) + Sq(q1-p1)) + Sq(q2-p2) ) = Sqrt( Sq(q0-p0) + Sq(q1-p1) + Sq(q2-p2) ).
Den metode for at udvide afstanden formlen fra to-dimensionelle rum til tre-dimensionelle rum kan anvendes flere gange i sidste ende at bestemme afstanden formlen for (d)-dimensionelle rum: Sqrt( (Sq(q0-p0) + Sq(q1-p1)) + Sq(q2-p2) + ... + Sq(qd-pd) ).
Nedenstående kode definerer en funktion kaldet "længde," der beregner længden af en (d)-dimensional vektor.
Når en vektor repræsenterer forskydning mellem to punkter i (d)-dimensionelle rum, længden af vektoren, udgør afstanden mellem disse to punkter.
public class VectorF64
{
// . . .
public double Length()
{
if (null == this.components)
{
return (0.0); // Vector empty.
}
int dimensions = this.Dimensions();
double sumOfSquares = 0.0;
for (int i = 0; i < dimensions; i++)
{
sumOfSquares += (this[i] * this[i]);
}
double length = Math.Sqrt( sumOfSquares );
return (length);
}
public static double Length( VectorF64 a )
{
if (null == a)
{
return (0.0); // Vector not specified.
}
if (null == a.components)
{
return (0.0); // Vector is empty.
}
return (a.Length());
}
// . . .
public static void Test()
{
// . . .
// Example of vector length:
// A 6-dimensional vector representing a point (p):
VectorF64 p = new VectorF64( 0.0, 1.0, 2.0, 3.0, 4.0, 5.0 );
p.WriteLine(); // ( 0, 1, 2, 3, 4, 5 )
// A 6-dimensional vector representing a point (q):
VectorF64 q = new VectorF64( -5.0, 4.0, -3.0, 2.0, -1.0, 0.0 );
q.WriteLine(); // ( -5, 4, -3, 2, -1, 0 )
// A 6-dimensional vector representing the displacement
// from point (p) to point (q):
VectorF64 r = q - p;
r.WriteLine(); // ( -5, 3, -5, -1, -5, -5 )
// The distance between point (p) and point (q)
// in 6-dimensional space:
double distance = r.Length();
Log.WriteLine( distance ); // 10.4880884817015
// . . .
}
}
3.10 (d)-dimensionelle vektorer: dot produkt
De "dot produkt" konverterer to (d)-dimensionelle vektorer til et nummer.
Nedenstående kode beregner en prik produkt af to vektorer:
public class VectorF64
{
// . . .
public static double Dot( VectorF64 a, VectorF64 b )
{
if ((null == a) ¦¦ (null == b))
{
return (0.0); // Vector not specified.
}
if ((null == a.components) ¦¦ (null == b.components))
{
return (0.0); // Vector is empty.
}
if (a.Dimensions() != b.Dimensions())
{
return (0.0); // Vectors not the same size.
}
int dimensions = a.Dimensions();
double dotProduct = 0.0;
for (int i = 0; i < dimensions; i++)
{
dotProduct += (a[i] * b[i]);
}
return (dotProduct);
}
// . . .
}
For enhver vektor, (A), Length(A) = Sqrt(Dot(A,A)).
3.11 (d)-dimensionelle vektorer: definition af "parallelle"
Vektorer (A) og (B) er "parallelle" hvis alle de følgende er sandt:
(1) A.Length() > 0;
(2) B.Length() > 0;
(3) Abs(Dot(A,B)) = A.Length()*B.Length().
Nedenstående kode afgør om et par af vektorer er parallelle (muligvis anti-tilpassede).
Floating-point tal kan ophobes fejl i fraktioneret dels skyldes den begrænsede præcision, og derfor, edb-kode bør omfatte ikke-nul tolerance når man sammenligner floating-point tal.
Koden omfatter eksempelvis tolerance værdier, men eksemplet tolerance værdier måske ikke være hensigtsmæssigt for nogle opgaver.
public class VectorF64
{
// . . .
public static bool Parallel( VectorF64 a, VectorF64 b )
{
// Smallest normalized float : 1.1754943e-38
// Smallest normalized double: 2.2250738585072020e-308
double nonZeroThreshold = 1.0e-38; // conservative for double
// double: (52+1)-bit mantissa; log10(2^53)=15.95 decimal digits
double fractionalDifferenceThreshold = 1.0e-14; // conservative
if ((null == a) ¦¦ (null == b))
{
return (false); // Vector is not specified.
}
if ((null == a.components) ¦¦ (null == b.components))
{
return (false); // Vector is empty.
}
if (a.Dimensions() != b.Dimensions())
{
return (false); // Vectors not the same size.
}
double lengthA = a.Length();
if (lengthA <= nonZeroThreshold)
{
return (false);
}
double lengthB = b.Length();
if (lengthB <= nonZeroThreshold)
{
return (false);
}
double oneImpliesParallel =
Math.Abs( VectorF64.Dot( a, b ) ) / (lengthA * lengthB);
double absoluteDifferenceFromOne =
Math.Abs( oneImpliesParallel - 1.0 );
if (absoluteDifferenceFromOne <= fractionalDifferenceThreshold)
{
return (true);
}
return (false);
}
// . . .
public static void Test()
{
// . . .
// Example of testing for parallel vectors:
// A 6-dimensional vector:
VectorF64 vf = new VectorF64( 0.0, 1.0, 2.0, 3.0, 4.0, 5.0 );
vf.WriteLine(); // ( 0, 1, 2, 3, 4, 5 )
// A 6-dimensional vector:
VectorF64 vg = new VectorF64( 0.0, -2.0, -4.0, -6.0, -8.0, -10.0 );
vg.WriteLine(); // ( 0, -2, -4, -6, -8, -10 )
// Determine if the specified vectors are parallel
// (or "anti-aligned"):
bool parallel = VectorF64.Parallel( vf, vg );
Log.WriteLine( parallel ); // True
// Add a non-negligible displacement to a component of a vector:
vf[0] += 1.0e-5;
vf.WriteLine(); // ( 1E-05, 1, 2, 3, 4, 5 )
// Determine if the specified vectors are parallel
// (or "anti-aligned"):
parallel = VectorF64.Parallel( vf, vg );
Log.WriteLine( parallel ); // False
// . . .
}
}
3.12 (d)-dimensionelle vektorer: definition af "vinkelret"
Vektorer (A) og (B) er "vinkelret" hvis alle de følgende er sandt:
(1) A.Length() > 0;
(2) B.Length() > 0;
(3) Abs(Dot(A,B)) = 0.
Nedenstående kode afgør om et par af vektorer er vinkelret. Floating-point tal kan ophobes fejl i fraktioneret dels skyldes den begrænsede præcision, og derfor, edb-kode bør omfatte ikke-nul tolerance når man sammenligner floating-point tal.
Koden omfatter eksempelvis tolerance værdier, men eksemplet tolerance værdier måske ikke være hensigtsmæssigt for nogle opgaver.
public class VectorF64
{
// . . .
public static bool Perpendicular( VectorF64 a, VectorF64 b )
{
// Smallest normalized float : 1.1754943e-38
// Smallest normalized double: 2.2250738585072020e-308
double nonZeroThreshold = 1.0e-38; // conservative for double
// double: (52+1)-bit mantissa; log10(2^53)=15.95 decimal digits
double fractionalDifferenceThreshold = 1.0e-14; // conservative
if ((null == a) ¦¦ (null == b))
{
return (false); // Vector is not specified.
}
if ((null == a.components) ¦¦ (null == b.components))
{
return (false); // Vector is empty.
}
if (a.Dimensions() != b.Dimensions())
{
return (false); // Vectors not the same size.
}
double lengthA = a.Length();
if (lengthA <= nonZeroThreshold)
{
return (false);
}
double lengthB = b.Length();
if (lengthB <= nonZeroThreshold)
{
return (false);
}
double zeroImpliesPerpendicular =
Math.Abs( VectorF64.Dot( a, b ) ) / (lengthA * lengthB);
double absoluteDifferenceFromZero =
Math.Abs( zeroImpliesPerpendicular );
if (absoluteDifferenceFromZero <= fractionalDifferenceThreshold)
{
return (true);
}
return (false);
}
// . . .
public static void Test()
{
// . . .
// Example of testing for perpendicular vectors:
// A 6-dimensional vector:
VectorF64 vf2 = new VectorF64( 0.0, 1.0, 2.0, 0.0, 4.0, 5.0 );
vf2.WriteLine(); // ( 0, 1, 2, 0, 4, 5 )
// A 6-dimensional vector:
VectorF64 vg2 = new VectorF64( 10.0, 0.0, 0.0, -5.0, 0.0, 0.0 );
vg2.WriteLine(); // ( 10, 0, 0, -5, 0, 0 )
// Determine if the specified vectors are perpendicular
bool perpendicular = VectorF64.Perpendicular( vf2, vg2 );
Log.WriteLine( perpendicular ); // True
// Add a non-negligible displacement to a component of a vector:
vf2[0] += 1.0e-13;
vf2.WriteLine(); // ( 1E-13, 1, 2, 0, 4, 5 )
// Determine if the specified vectors are perpendicular
perpendicular = VectorF64.Perpendicular( vf2, vg2 );
Log.WriteLine( perpendicular ); // False
// . . .
}
}
3.13 Matricer
"Matrix:" En samling af variabler, sådan at hver variabel har en unik kombination af en "række" navn og en "kolonne" navn.
"indrejse:" En variabel inden for en matrix.
Integer værdier kan bruges som "rækken" navne og "kolonne" navne til variabler i en matrix.
For eksempel, hvis en matrix har (totalRows) rækker og (totalColumns) kolonner, så integer værdier { 0, 1, ..., (totalRows-1) } kan være navne tildeles de rækker, og integer værdier { 0, 1, ..., (totalColumns-1) } kan være navne tildeles de kolonner.
Således er en variabler i en matrix kan angives ved at angive et par af heltal, ( row, column ), hvilket tyder på en kombination af række og kolonne indekser svarer til de specifikke variabel.
Størrelsen af en matrix er angivet som "(totalRows) * (totalColumns)" (eller "(totalRows) ved (totalColumns))."
Denne kendelse af dimensioner er den samme som rækkefølgen af dimensioner bruges til at angive poster i matrix "(( row, column ))."
[Denne konvention er lidt uheldigt, fordi for mange to-dimensional anvendelser (eksempler: billeder, grafer osv.) den sædvanlige konvention er at angive dimensioner som "width * height" og koordinerer som "( horizontal, vertical )" (eller "( x, y ))."
Dette er det modsatte af rækkefølgen af dimensioner og koordinater bruges til at beskrive matricer og deres poster. ]
En matrix med (totalRows) lig med (totalColumns) er opkaldt "square" ellers, matrix er opkaldt "rektangulære."
En matrix kan betragtes som indeholdende et sæt af "rækken vektorer," hvor variabler i hver række er fortolkes som tilhørende en vektor.
En matrix kan også betragtes som indeholdende et sæt "kolonne vektorer," hvor variabler i hver kolonne er fortolkes som tilhørende en vektor.
Matricer kan repræsentere en bred vifte af matematiske relationer.
Betydningen af en matrix, og de operationer, som kan være relevante for behandling poster i en matrix, afhænger af konteksten.
Der er dog grundlæggende regler i matrix regning, der er relevante i mange sammenhænge, og disse grundlæggende regler vil blive fastlagt i et senere afsnit.
En matrix og en (totalColumns) værdi er tilstrækkelige til at repræsentere en matrix.
De array kan have (totalRows * totalColumns) variabler, og optagelse på ( row, column ) kan svare til array variabel i indekset ((totalColumns * row) + column).
Nedenstående kode definerer en matrix, med 64-bit floating-point poster.
En matrix og en (totalColumns) værdi er tilstrækkelige til at repræsentere en matrix.
Nedenstående kode er en matrix og en (totalColumns) værdi er indeholdt i en klasse, kun for bekvemmelighed.
Nedenstående kode er ikke beregnet til at blive effektiv.
En struktur (eksempel: "struct" en værdi type) repræsenterer matricer af særlig faste dimensioner (eksempler: 2*2, 3*3, eller 4*4) må forventes at være langt mere effektiv end den generelle (totalRows * totalColumns) klassen vist her.
Selv om koden nedenfor definerer en matrix med floating-point poster, giver denne artikel også gør brug af matricer med heltal poster.