Algebra liniara
Colin Fahey
1. Software
LinearAlgebra.zip
Algebra liniara codul sursă (C#)
19910 octeţi
MD5: 11d8c8035cac30ba543e5e0b72ee9767
2. Introducere
Acest articol descrie vectori şi matrici (d)-dimensionale în spaţiu.
3. (d)-dimensional space: Atribute
3.1 Array
"matrice:" O colectie de variabile, astfel încât fiecare variabilă are un nume unic, şi de asemenea că numele poate fi atribuit un ordin.
Valori pot fi utilizate ca nume de variabile într-o matrice.
De exemplu, dacă un array (d) conţine variabile, atunci valori { 0, 1, 2, ..., (d-1) } poate fi numele atribuit de variabile în matrice.
3.2 (d)-dimensional vector
"(d)-dimensional vector:" un array de (d) variabile.
"vector pe componente:" o variabilă într-un vector.
3.3 (d)-dimensional vector spaţiu
"o-dimensional space:" set complet de valori care pot fi stocate de către o variabilă.
"(d)-dimensional space:" set complet de combinaţii de valori care pot fi stocate de către o serie de variabile (d).
Formale, definirea unui "spatiu vectorial:"
Să (T) fi o bază de tip (exemple: numărul real, întreg, numărul de complexe, număr raţional, etc.)
Orice variabila de un tip de bază este numit un "scalar."
Un "tip (T)-(d)-dimensional vector spaţiu" este un set (S) de (d)-dimensional vectori având două operaţii, plus (+) vector, scalar şi multiplicare (*), care îndeplinesc condiţiile de mai jos:
(1) Dacă (v) şi (w) sunt doi vectori în orice (S), apoi (v + w) este, de asemenea, un vector în (S);
(2) Dacă (u), (v), şi orice (w) sunt trei vectori în (S), apoi (u + v) + w = u + (v + w);
[aditiv commutativity]
(3) Dacă (v) şi (w) sunt doi vectori în orice (S), apoi (v + w) = (w + v);
[aditiv associativity]
(4) Există un "vector de zero," (0), în (S), astfel că pentru orice vector (v) în (S), (v + (0)) = v;
[aditiv de identitate]
(5) Dacă este (c) orice tip de scalare (T), şi este (v) orice vector în (S), apoi produsul (c * v) este un vector în (S);
(6) Dacă (a), (b), şi (c) sunt scalars orice tip de (T), şi (v) şi (w) sunt vectori în orice (S), apoi (a + b) * v = a*v + b*v, şi c*(v + w) = c*v + c*w;
[multiplicativ distributivity]
(7) Dacă (a) şi (b) sunt scalars orice tip de (T), şi este (v) orice vector în (S), apoi (a*b)*v = a*(b*v);
(8) Dacă "1" este un tip de scalare (T) astfel că (1*1)=1, şi este (v) orice vector în (S), apoi (1*v) = v;
(9) Pentru fiecare vector (v) în (S), vectorul (-1)*v = -v îndeplineşte v + (-v) = (0);
[aditiv invers]
3.4 (d)-dimensional vector de cod
Codul de mai jos arată modul în care o (d)-dimensional vector, cu 64 de biţi în virgulă flotantă punct de componente, pot fi puse în aplicare.
O matrice este suficientă pentru a reprezenta un vector.
Codul de mai jos are un array conţinute într-o clasă, doar pentru comoditate.
Acest cod nu este destinat a fi eficiente.
O structură (de exemplu: "struct", un tip de valoare) reprezintă vectori de un număr fix de dimensiuni (exemple: 3 sau 4) este probabil să fie mult mai eficient decât generale (d)-dimensional vector clasa arătat aici.
Desi codul de mai jos defineşte un vector cu plutitor-punct de componente, acest document, de asemenea, face uz de vectori cu componente număr întreg.
Codul de mai jos pot fi uşor modificate pentru punerea în aplicare a vectorilor cu număr întreg de componente.
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) zero-dimensional vector:" Un vector cu toate componentele (d) egal cu zero.
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)-dimensional spatiu: puncte
"(d)-dimensional spaţiu punct:" un array de (d) specifice, cu valori variabile "(valori de coordonate)."
"(d)-dimensional spaţiu origine:" un array de (d) toate variabilele cu valori egale cu zero.
3.6 (d)-dimensional vectori: non-relative şi relativă
Un (d)-dimensional vector care "nu" este "relativă" este o (d)-dimensional vector care, direct sau reprezinta o stare de configurare.
Un (d)-dimensional vector care este "relativă" este o (d)-dimensional, care reprezinta vectorul de modificări la un set de componente.
Un vector relativă poate reprezenta diferenţa dintre doi vectori nu-relativă.
Având în vedere o ruda vectorială, determinarea unei non-relativ de statutul sau de configurare, folosind ca vector relativă, care necesită combinarea cu un vector relativ non-vectorială relativă.
Non-relativă şi relativă vectorilor vectorii sunt atât vectori.
Dacă un anumit vector nu este relativă sau relativă trebuie să fie specificat, atunci când vectorul este definit.
Dacă un (d)-dimensional vector este interpretat ca fiind non-relativă, atunci (d)-dimensional vector poate reprezenta un punct în spaţiu (d)-dimensional.
3.7 (d)-dimensional vector plus, Navigare, şi scalarea
Vector plus, Navigare, şi scalarea:
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 baza vectorilor
Formale, definirea unui "baza" unui spatiu vectorial:
Să (T) fi o bază de tip (exemple: numărul real, întreg, numărul de complexe, număr raţional, etc.)
Orice variabila de un tip de bază este numit un "scalar."
Să (V) fi un "(T) de tip (d)-dimensional vectorul spatiu."
În cazul în care non-zero vectori { u1, u2, ..., ud } în (V) sunt de aşa natură încât în fiecare vector (v) în (V) poate fi scrisă ca o "combinaţie liniară" a acestor vectori, v = c1*u1 + c2*u2 + ... + cd*ud, în cazul în care { c1, c2, ..., cd } sunt scalars de tip (T), apoi (V) este "spanned" prin vectori { u1, u2, ..., ud }.
Orice set de non-zero vectori { u1, u2, ..., ud } că "span" spatiu vectorial (V) este numit pe "baza" de (V).
Un simplu "baza" unui (d)-dimensional vector spaţiu este un set de (d) distincte (d)-dimensional vectori, fiecare cu o componentă egală cu unul şi toate celelalte componente egale cu zero.
Astfel de baza vectorilor sunt "orthonormal," ceea ce înseamnă că acestea sunt reciproc "perpendiculare-(orthogonal)" şi că fiecare unitate a vectorului lungime.
Fiecare astfel de unitate vectorul este un vector paralel cu una dintre axele de coordonate (d).
Exprimându-un vector arbitrar ca o "combinaţie liniară" a acestor vectori este de baza directe; fiecare componentă a vectorului este arbitrară, înmulţită cu vectorul baza corespunzătoare, şi aceste produse sunt adăugate împreună pentru a forma de vector arbitrar.
Codul de mai jos arată cum un vector poate fi exprimat ca o "combinaţie liniară de" vectorii de baza.
Codul de mai jos în mod arbitrar orthonormal defineşte un set de baza vectorilor.
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 )
// . . .
}
}
Orice vector în spaţiul (d)-dimensionale pot fi exprimate ca o sumă de produse de baza si numere de vectori:
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)-dimensional spaţiu: distanţa dintre punctele
Să (P) fi un (d)-dimensional vector care reprezintă un punct în spaţiu (d)-dimensional.
Să (Q) fi un (d)-dimensional vector care reprezintă un punct în spaţiu (d)-dimensional.
Să (R) fi un (d)-dimensional, care reprezinta vectorul de schimbare în (d) coordonate pentru a obţine de la punctul de a (P) punct (Q); R = (Q - P).
Într-un spaţiu-dimensional, P = ( p0 ), Q = ( q0 ), şi R = (Q - P) = ( q0 - p0 ).
Distanţa dintre cele două puncte este: Abs( q0 - p0 ).
În spaţiul bidimensional, P = ( p0, p1 ), Q = ( q0, q1 ), şi R = (Q - P) = ( q0-p0, q1-p1 ).
Interpretarea celor doua perpendiculare deplasarilor ca perpendicular laturile unui triunghi din dreapta, distanţa între puncte corespunde cu lungimea de hypotenuse din acest triunghi.
Pythagorean de formulă, (a*a) + (b*b) = (c*c), în cazul în care (a) şi (b) sunt perpendiculare de lungimi de laturi a unui triunghi din dreapta, şi (c) este lungimea de hypotenuse (skew parte), pot fi utilizate pentru a determina distanţa dintre cele două puncte: Sqrt( Sq(q0-p0) + Sq(q1-p1) ).
În tri-dimensională de spatiu, P = ( p0, p1, p2 ), Q = ( q0, q1, q2 ), şi R = (Q - P) = ( q0-p0, q1-p1, q2-p2 ).
Interpretarea deplasament ( q0-p0, q1-p1, 0 ) ca perpendicular laturile unui triunghi din dreapta, şi folosind formula de Pythagorean, dă distanţa dintre punctul (P) şi punctul ( q0, q1, p2 ): d01 = Sqrt( Sq(q0-p0) + Sq(q1-p1) ).
Deplasarea ( q0-p0, q1-p1, 0 ) este perpendicular pe ( 0, 0, q2-p2 ) deplasare, precum şi a unui alt drept-triunghi se pot forma, precum şi Pythagorean formulă poate fi utilizat din nou.
Astfel, distanta de la punctul de a (P) punct (Q) este data de: 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) ).
Metoda de extindere a formulei de la distanta bidimensional spaţiu pentru a tri-dimensională de spaţiu să poată fi aplicate în mod repetat pentru a determina distanţa formulă pentru (d)-dimensional spaţiu: Sqrt( (Sq(q0-p0) + Sq(q1-p1)) + Sq(q2-p2) + ... + Sq(qd-pd) ).
Codul de mai jos defineşte o funcţie numită "Lungime" care computes lungimea unei (d)-dimensional vector.
Atunci când un vector reprezintă deplasarea între două puncte în spaţiu (d)-dimensional, lungimea vectorului reprezintă distanţa dintre cele două puncte.
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)-dimensional vectori: dot produs
"Punct" de "produs" converteşte doi (d)-dimensională la un număr de vectori.
Codul de mai jos computes punct un produs de doi vectori:
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);
}
// . . .
}
Pentru orice vector, (A), Length(A) = Sqrt(Dot(A,A)).
3.11 (d)-dimensional vectori: definiţie a "paralel"
Vectorilor (A) şi (B) sunt "paralele," dacă toate condiţiile următoare sunt adevărate:
(1) A.Length() > 0;
(2) B.Length() > 0;
(3) Abs(Dot(A,B)) = A.Length()*B.Length().
Codul de mai jos determină dacă o pereche de vectori sunt paralele (eventual anti-aliniate).
Plutitor-punct de numere pot acumula erori in parte din cauza fragmente limitate de precizie, şi, prin urmare, computerul ar trebui să includă codul de non-zero, atunci când toleranţele compararea plutitoare-punct de numere.
Codul include valorile exemplu de toleranţă, ci toleranţă de exemplu, valorile ar putea să nu fie potrivite pentru anumite sarcini.
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)-dimensional vectori: definiţie a "perpendicular"
Vectorilor (A) şi (B) sunt "perpendiculare" dacă toate condiţiile următoare sunt adevărate:
(1) A.Length() > 0;
(2) B.Length() > 0;
(3) Abs(Dot(A,B)) = 0.
Codul de mai jos determină dacă o pereche de vectori sunt perpendiculare. Plutitor-punct de numere pot acumula erori in parte din cauza fragmente limitate de precizie, şi, prin urmare, computerul ar trebui să includă codul de non-zero, atunci când toleranţele compararea plutitoare-punct de numere.
Codul include valorile exemplu de toleranţă, ci toleranţă de exemplu, valorile ar putea să nu fie potrivite pentru anumite sarcini.
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 Matrices
"matrice:" O colectie de variabile, astfel încât fiecare variabilă are o combinaţie unică a unui nume de "rând" şi o "coloană" nume.
"intrare:" o variabilă într-o matrice.
Valori pot fi utilizate ca nume de "rând" şi de "coloană" pentru numele de variabile într-o matrice.
De exemplu, dacă o matrice a (totalRows) rânduri şi de coloane (totalColumns), atunci valori { 0, 1, ..., (totalRows-1) } poate fi numele atribuit de rânduri, şi de valori { 0, 1, ..., (totalColumns-1) } poate fi numele atribuit de coloane.
Astfel, o variabile într-o matrice pot fi specificate prin specificarea unei perechi de întregi, ( row, column ), indicând combinaţie a rândul şi coloana corespunzătoare pentru a indicilor specifice de variabilă.
Dimensiunea unei matrice este specificat ca "(totalRows) * (totalColumns)" (sau "(totalRows) de (totalColumns))."
Acest ordin de dimensiuni este aceeaşi cu ordinea de dimensiuni utilizate pentru a specifica intrări în matrice "(( row, column ))."
[Această convenţie este oarecum unfortunate, deoarece pentru multe utilizări bidimensional (exemple: imagini, grafice, etc) ca de obicei de convenţie este de a specifica dimensiunile "width * height" ca şi coordonate ca "( horizontal, vertical )" (sau "( x, y ))."
Aceasta este opusul ordinea de dimensiuni şi coordonate folosit pentru a descrie matrici şi intrările lor. ]
O matrice cu (totalRows) egală cu (totalColumns) este numit "pătrat;" altfel, este numit matrice "dreptunghiular."
O matrice poate fi privită ca conţinând un set de "vectori rând," în cazul în care variabilele în fiecare rând sunt interpretate ca aparţinând unui vector.
O matrice poate fi, de asemenea, considerate ca fiind conţine un set de "vectori coloană," în cazul în care variabilele în fiecare coloană sunt interpretate ca aparţinând unui vector.
Matrices poate reprezenta o mare varietate de relaţii matematice.
În sensul unei matrice, precum şi operaţiunile care ar putea fi potrivite pentru prelucrare, inregistrarile de o matrice, depinde de context.
Cu toate acestea, există reguli de baza de matrice aritmetic care sunt relevante pentru mai multe contexte, iar aceste norme de bază vor fi definite într-o secţiune ulterioară.
Un array si o valoare (totalColumns) sunt suficiente pentru a reprezenta o matrice.
De matrice poate avea (totalRows * totalColumns) variabile, de la intrarea şi la ( row, column ) poate să corespundă cu matrice variabilă de la indexul ((totalColumns * row) + column).
Codul de mai jos defineşte o matrice, cu 64 de biţi în virgulă flotantă punct de intrări.
Un array si o valoare (totalColumns) sunt suficiente pentru a reprezenta o matrice.
Codul de mai jos are un array si o valoare (totalColumns) conţinute într-o clasă, doar pentru comoditate.
Codul de mai jos nu este destinat a fi eficiente.