Algebra lineare
Colin Fahey
1. Software
LinearAlgebra.zip
Algebra lineare codice sorgente (C#)
19910 byte
MD5: 11d8c8035cac30ba543e5e0b72ee9767
2. Introduzione
In questo articolo viene descritto vettori e matrici in (d)-dimensionale spazio.
3. (d)-dimensionale spazio: attributi
3.1 Array
“array:„ Una raccolta di tali variabili che ogni variabile ha un nome univoco, e tale che il nome può essere assegnato un ordine.
Valori interi possono essere utilizzati come nomi per le variabili in un array.
Ad esempio, se un array contiene (d) variabili, quindi la { 0, 1, 2, ..., (d-1) } valori interi possono essere i nomi assegnati alle variabili nella matrice.
3.2 (d)-dimensionale Vector
“(d)-dimensionale vettore:„ una serie di variabili (d).
“vettore componente:„ una variabile all'interno di un vettore.
3.3 (d)-dimensionale spazio vettoriale
“uno spazio-dimensionale:„ Il set completo di valori che possono essere archiviati da una variabile.
“(d)-dimensionale spazio:„ La serie completa di combinazioni di valori che possono essere archiviati da una serie di variabili (d).
La definizione formale di uno “spazio vettoriale:„
Lasciate (T) essere un tipo di base (esempi: numero reale, intero, numero complesso, numero razionale, ecc.)
Qualsiasi variabile di un tipo di base è chiamato un “scalare.„
Un “(T) di tipo (d)-dimensionale spazio vettoriale„ è l'insieme (S) di (d)-dimensionale vettori che hanno due operazioni, oltre (+) vettore, e scalare (*) moltiplicazione, che soddisfano le condizioni seguenti:
(1) Se (v) e (w) sono due vettori in (S), quindi (v + w) è anche un vettore in (S);
(2) Se (u), (v), e (w) sono di tre vettori in (S), quindi (u + v) + w = u + (v + w);
[additivo commutativity]
(3) Se (v) e (w) sono due vettori in (S), quindi (v + w) = (w + v);
[additivo Associatività]
(4) Vi è un “vettore zero,„ (0), in (S), tale che per ogni vettore (v) in (S), (v + (0)) = v;
[additivo identità]
(5) Se è (c) qualsiasi tipo di scalare (T), e (v) è un qualsiasi vettore in (S), quindi il prodotto (c * v) è un vettore in (S);
(6) Se (a), (b), e (c) sono scalari di qualsiasi tipo (T), e (v) e (w) sono vettori in qualsiasi (S), quindi (a + b) * v = a*v + b*v, e c*(v + w) = c*v + c*w;
[moltiplicativo Distributività]
(7) Se (a) e (b) sono scalari di qualsiasi tipo (T), e (v) è un qualsiasi vettore in (S), quindi (a*b)*v = a*(b*v);
(8) Se “1„ è un tipo di scalare (T) tale che (1*1)=1, e (v) è un qualsiasi vettore in (S), quindi (1*v) = v;
(9) Per ogni vettore (v) in (S), il vettore (-1)*v = -v soddisfa v + (-v) = (0);
[additivo inverso]
3.4 (d)-dimensionale Vector codice
Il codice qui sotto mostra come una (d) vettore-dimensionale, con 64-bit in virgola mobile componenti, può essere implementato.
Un array è sufficiente a rappresentare un vettore.
Il codice qui sotto ha una matrice contenuta in una classe, solo per comodità.
Il codice non è destinato ad essere efficace.
Una struttura (ad esempio: “struct„, un tipo di valore) che rappresentano vettori di un numero fisso di dimensioni (esempi: 3 o 4) rischia di essere molto più efficienti di quelli generali (d)-vettore classe dimensionale mostrato qui.
Sebbene il codice qui sotto definisce un vettore con virgola mobile componenti, questo documento fa anche uso di vettori con componenti intero.
Il codice qui sotto può essere facilmente modificato per attuare con vettori intero componenti.
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)-dimensionale zero vettore:„ un vettore con tutti i componenti (d) pari a 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)-dimensionale spazio: punti
“(d)-dimensionale spazio punto:„ una serie di (d) variabili con valori specifici “(valori delle coordinate).„
“(d)-dimensionale spazio origine:„ una serie di variabili (d) con tutti i valori pari a zero.
3.6 (d)-dimensionale vettori: non relativa e relativa
Un (d)-dimensionale vettore che “non„ è “parente„ è un (d)-dimensionale vettore che direttamente rappresenta una situazione o configurazione.
Un (d) vettore-dimensionale che è “relativo„ è un (d)-dimensionale vettore che rappresenta le modifiche a un insieme di componenti.
Un parente vettore può rappresentare la differenza tra i due non relativi vettori.
Dato un vettore relativa, determinando un non-stato e relativa configurazione utilizzando relativa vettore che richiede che unisce la relativa vettore con una percentuale di non rispetto vettore.
Non relativi vettori e relativi vettori sono entrambi vettori.
Se un particolare vettore non è parente o un parente deve essere specificato quando il vettore è definito.
(d) se un vettore-dimensionale viene interpretato come non relativa, quindi la (d)-dimensionale vettore può rappresentare un punto in (d)-dimensionale spazio.
3.7 (d)-dimensionale vettore addizione, sottrazione, e scaling
Vettore di addizione, sottrazione, e scaling:
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)-dimensionale base vettori
La definizione formale di una “base„ di uno spazio vettoriale:
Lasciate (T) essere un tipo di base (esempi: numero reale, intero, numero complesso, numero razionale, ecc.)
Qualsiasi variabile di un tipo di base è chiamato un “scalare.„
Lasciate (V) essere un “(T) di tipo (d)-dimensionale spazio vettoriale.„
Se il non-zero vettori { u1, u2, ..., ud } in (V) sono tali che ogni vettore (v) in (V) può essere scritto come “combinazione lineare„ di tali vettori, v = c1*u1 + c2*u2 + ... + cd*ud, dove sono { c1, c2, ..., cd } scalari di tipo (T), allora è (V) “spanning„ di vettori { u1, u2, ..., ud }.
Un gruppo di non-zero vettori che { u1, u2, ..., ud } “span„ spazio vettoriale (V) è chiamato a “base„ di (V).
Una semplice “base„ di una (d)-dimensionale spazio vettoriale è l'insieme di (d) distinti (d)-dimensionale vettori, ciascuno con un elemento pari a uno e tutti gli altri componenti pari a zero.
Base di tali vettori sono “Orthonormal,„ il che significa che esse sono reciprocamente-perpendicolare “(ortogonale)„ e che ogni vettore ha unità di lunghezza.
Ciascuno di tali vettori è un vettore unitario parallelo ad uno degli coordinerà (d) assi.
Esprimendo un arbitrario vettore come “combinazione lineare„ di questi vettori di base è diretta; componente di ogni arbitrario il vettore è moltiplicato per il corrispondente vettore di base, e questi prodotti sono aggiunti insieme per formare il vettore arbitrario.
Il codice qui sotto mostra come un vettore può essere espresso come “combinazione lineare„ di vettori di base.
Il codice qui sotto arbitrariamente Orthonormal definisce un insieme di vettori di base.
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 )
// . . .
}
}
Qualsiasi vettore in (d)-dimensionale spazio può essere espresso come somma dei prodotti di numeri e vettori di base:
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)-dimensionale spazio: la distanza tra i punti
Lasciate (P) essere un (d)-dimensionale vettore che rappresenta un punto in (d)-dimensionale spazio.
Lasciate (Q) essere un (d)-dimensionale vettore che rappresenta un punto in (d)-dimensionale spazio.
Lasciate (R) essere un (d)-dimensionale vettore che rappresenta la variazione del (d) coordinate per andare dal punto (P) a punto (Q); R = (Q - P).
In uno spazio-dimensionale, P = ( p0 ), Q = ( q0 ), e R = (Q - P) = ( q0 - p0 ).
La distanza tra i due punti è: Abs( q0 - p0 ).
In due dimensioni spazio, P = ( p0, p1 ), Q = ( q0, q1 ), e R = (Q - P) = ( q0-p0, q1-p1 ).
Interpretare le due perpendicolari spostamenti come la perpendicolare lati di un triangolo-destra, la distanza fra i punti corrisponde alla lunghezza del hypotenuse di quel triangolo.
Pythagorean la formula, (a*a) + (b*b) = (c*c), dove (a) e (b) sono le lunghezze dei lati perpendicolari di un diritto-triangolo, e (c) è la lunghezza della hypotenuse (skew lato), può essere usato per determinare la distanza tra i due punti: Sqrt( Sq(q0-p0) + Sq(q1-p1) ).
In spazio tridimensionale, P = ( p0, p1, p2 ), Q = ( q0, q1, q2 ), e R = (Q - P) = ( q0-p0, q1-p1, q2-p2 ).
Interpretando lo spostamento ( q0-p0, q1-p1, 0 ) come la perpendicolare lati di un triangolo-destra, e utilizzando la formula Pythagorean, ha pronunciato la distanza tra il punto (P) e il punto ( q0, q1, p2 ): d01 = Sqrt( Sq(q0-p0) + Sq(q1-p1) ).
Lo spostamento ( q0-p0, q1-p1, 0 ) è perpendicolare allo sfollamento ( 0, 0, q2-p2 ), e un altro destro del triangolo può essere formato, e la Pythagorean formula può essere usato di nuovo.
Così, la distanza dal punto (P) a punto (Q) è dato da: 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) ).
Il metodo di estendere la formula di distanza da due dimensioni spazio a spazio tridimensionale può essere applicato più volte per poi determinare la distanza formula per (d)-dimensionale spazio: Sqrt( (Sq(q0-p0) + Sq(q1-p1)) + Sq(q2-p2) + ... + Sq(qd-pd) ).
Il codice qui sotto definisce una funzione denominata “Lunghezza„ che calcola la lunghezza di una (d) vettore-dimensionale.
Quando un vettore rappresenta lo spostamento tra due punti in (d)-dimensionale spazio, la lunghezza del vettore rappresenta la distanza tra questi due punti.
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)-dimensionale vettori: dot prodotto
Il “punto prodotto„ converte due (d)-dimensionale vettori a un numero.
Il codice qui sotto calcola un punto prodotto di due vettori:
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);
}
// . . .
}
Per ogni vettore, (A), Length(A) = Sqrt(Dot(A,A)).
3.11 (d)-dimensionale vettori: definizione di “parallelo„
(A) vettori e (B) sono “paralleli„ se tutte le seguenti condizioni:
(1) A.Length() > 0;
(2) B.Length() > 0;
(3) Abs(Dot(A,B)) = A.Length()*B.Length().
Il codice qui sotto determina se una coppia di vettori sono paralleli (eventualmente anti-allineati).
Numeri floating-point possono accumulare errori nella parte frazionaria a causa della limitata precisione, e, quindi, di codice dovrebbe includere non-zero tolleranze, se si confrontano i numeri floating-point.
Il codice di esempio include i valori di tolleranza, ma l'esempio di tolleranza valori potrebbero non essere appropriato per alcuni compiti.
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)-dimensionale vettori: definizione di “perpendicolare„
(A) vettori e (B) sono “perpendicolari„ se tutte le seguenti condizioni:
(1) A.Length() > 0;
(2) B.Length() > 0;
(3) Abs(Dot(A,B)) = 0.
Il codice qui sotto determina se una coppia di vettori sono perpendicolari. Numeri floating-point possono accumulare errori nella parte frazionaria a causa della limitata precisione, e, quindi, di codice dovrebbe includere non-zero tolleranze, se si confrontano i numeri floating-point.
Il codice di esempio include i valori di tolleranza, ma l'esempio di tolleranza valori potrebbero non essere appropriato per alcuni compiti.
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 Matrici
“matrice:„ Una raccolta di tali variabili che ogni variabile è una combinazione unica di una “riga„ nome e un nome di “colonna.„
“ingresso:„ una variabile all'interno di una matrice.
Valori interi possono essere utilizzati come nomi di “riga„ e “colonna di„ nomi per le variabili in una matrice.
Ad esempio, se una matrice ha (totalRows) righe e colonne (totalColumns), allora la valori interi { 0, 1, ..., (totalRows-1) } può essere il nome assegnato al file, e la { 0, 1, ..., (totalColumns-1) } valori interi possono essere i nomi assegnati alle colonne.
Pertanto, una variabili in un modello che può essere specificato indicando un paio di numeri interi, ( row, column ), con l'indicazione della combinazione di riga e colonna indici corrispondenti alle specifiche variabile.
Le dimensioni di una matrice è specificato come “(totalRows) * (totalColumns)„ (o “(totalRows) di (totalColumns)).„
Questo ordine di dimensioni è lo stesso che l'ordine di dimensioni utilizzato per specificare le voci nella matrice “(( row, column )).„
[Questa convenzione è un po 'un peccato, perché per molti bidimensionale usi (esempi: immagini, grafici, ecc) la solita convenzione è quello di specificare le dimensioni come “width * height„ e coordina come “( horizontal, vertical )„ (o “( x, y )).„
Questo è l'opposto dell 'ordine di dimensioni e le coordinate usato per descrivere le matrici e le loro voci. ]
Una matrice con (totalRows) pari al (totalColumns) è chiamato “quadrato,„ altrimenti la matrice è chiamato “rettangolare.„
Una matrice può essere considerata come contenente una serie di “vettori riga,„ dove le variabili in ciascuna riga vengono interpretati come appartenenti a un vettore.
Una matrice può anche essere considerata come contenente una serie di “vettori colonna,„ in cui le variabili in ogni colonna vengono interpretati come appartenenti a un vettore.
Matrici possono rappresentare una grande varietà di rapporti matematici.
Il significato di una matrice, e le operazioni che potrebbero essere appropriati per la trasformazione di voci di una matrice, dipende dal contesto.
Tuttavia, vi sono regole di base della matrice aritmetica che sono rilevanti per molti contesti, e queste regole di base verranno definite in una successiva sezione.
Un array e un valore (totalColumns) sono sufficienti a rappresentare una matrice.
L'array può avere (totalRows * totalColumns) variabili, e la data di entrata in ( row, column ) può corrispondere a matrice variabile a Indice ((totalColumns * row) + column).
Il codice qui sotto definisce una matrice, con 64-bit in virgola mobile voci.
Un array e un valore (totalColumns) sono sufficienti a rappresentare una matrice.
Il codice qui sotto è un array e un valore (totalColumns) contenute in una classe, solo per comodità.
Il codice qui sotto non è destinato ad essere efficace.
Una struttura (ad esempio: “struct„, un tipo di valore), che rappresentano particolare matrici di dimensioni fisse (esempi: 2*2, 3*3, o 4*4) rischia di essere molto più efficienti di quelli