Γραμμική Άλγεβρα
Colin Fahey
1. Λογισμικό
LinearAlgebra.zip
Γραμμική άλγεβρα πηγαίο κώδικα (C#)
19910 bytes
MD5: 11d8c8035cac30ba543e5e0b72ee9767
2. Εισαγωγή
Αυτό το άρθρο περιγράφει διανύσματα και πίνακες σε (d) διαστάσεων χώρο.
3. (d) διαστάσεων χώρο: χαρακτηριστικά
3.1 Array
"array:" Μια συλλογή από μεταβλητές τέτοιες ώστε κάθε μεταβλητή έχει ένα μοναδικό όνομα, και τα ονόματα αυτών που μπορεί να καταταχθεί σε κάποια τάξη.
Ακέραιος τιμές μπορούν να χρησιμοποιηθούν ως ονόματα για τις μεταβλητές σε έναν πίνακα.
Για παράδειγμα, εάν μια σειρά περιέχει (d) μεταβλητές, τότε ο ακέραιος { 0, 1, 2, ..., (d-1) } τιμές μπορεί να είναι το ονόματα που αποδίδονται στις μεταβλητές της συστοιχίας.
3.2 (d) διαστάσεων φορέα
"(d) διαστάσεων φορέα:" Μια σειρά από μεταβλητές (d).
"διανυσματική συνιστώσα:" Μια μεταβλητή μέσα σε ένα φορέα.
3.3 (d) διαστάσεων διανυσματικό χώρο
"μονοδιάστατη διάστημα:" Το πλήρες σύνολο των αξιών που μπορούν να αποθηκευτούν από ένα μεταβλητό.
"(d) διαστάσεων χώρο:" Η πλήρης σειρά των συνδυασμών των αξιών που μπορούν να αποθηκευτούν από μια σειρά από μεταβλητές (d).
Ο επίσημος ορισμός ενός "φορέα διάστημα:"
Ας (T) να είναι ένας βασικός τύπος (παραδείγματα: πραγματικός αριθμός, ακέραιος, αριθμός πολύπλοκων, ορθολογική αριθμό, κλπ).
Κάθε μεταβλητή του βασικού τύπου ονομάζεται "μονοδιάστατη."
Μια "(T) τύπου (d) διαστάσεων του φορέα" είναι ο "χώρος" που (S) των (d) διαστάσεων φορέων έχοντας δύο επιχειρήσεων, φορέων (+) Επιπλέον, τον πολλαπλασιασμό και τη μονοδιάστατη (*), οι οποίοι πληρούν τις παρακάτω προϋποθέσεις:
(1) Εάν (v) και (w) οι δύο φορείς σε (S), τότε (v + w) είναι επίσης ένα φορέα στον (S)?
(2) Εάν (u), (v), και (w) είναι τριών φορέων σε (S), τότε (u + v) + w = u + (v + w)?
[ύλης commutativity]
(3) Εάν (v) και (w) οι δύο φορείς σε (S), τότε (v + w) = (w + v)?
[ύλης associativity]
(4) Υπάρχει ένα "μηδενικό φορέα," (0), (S), τέτοια ώστε για κάθε φορέα (v) στο (S), (v + (0)) = v?
[ύλης ταυτότητα]
(5) Αν τυχόν (c) είναι μονοδιάστατη (T) του τύπου, και (v) είναι κάθε φορέα στο (S), τότε το προϊόν (c * v) αποτελεί φορέα στον (S)?
(6) Εάν (a), (b), και (c) είναι κάθε scalars του τύπου (T), και (v) και (w) είναι φορείς σε κάθε (S), τότε (a + b) * v = a*v + b*v, και c*(v + w) = c*v + c*w?
[multiplicative distributivity]
(7) Εάν (a) και (b) είναι κάθε scalars του τύπου (T), και (v) είναι κάθε φορέα στο (S), τότε (a*b)*v = a*(b*v)?
(8) Αν "1" είναι μια μονοδιάστατη του τύπου (T) τέτοια που (1*1)=1, και (v) είναι κάθε φορέα στο (S), τότε (1*v) = v?
(9) Για κάθε φορέα (v) στο (S), τον φορέα (-1)*v = -v πληροί v + (-v) = (0)?
[προσθετικό αντίστροφο]
3.4 (d) διαστάσεων φορέα κωδικός
Ο κώδικας που ακολουθεί δείχνει πώς μια (d) διαστάσεων φορέα, με 64-bit floating-point συστατικά, μπορούν να εφαρμοστούν.
Ένας array είναι αρκετή για να αποτελέσει φορέα.
Ο κώδικας έχει κάτω από ένα array που περιέχονται σε μια τάξη, μόνο για λόγους ευκολίας.
Ο κωδικός αυτός δεν είναι αποτελεσματική.
Μια δομή (π.χ.: "struct", μια τιμή τύπου) που εκπροσωπούν φορείς του σταθερού αριθμού των διαστάσεων (παραδείγματα: 3 ή 4) είναι πιθανό να είναι πολύ πιο αποτελεσματική από τη γενική (d) διαστάσεων φορέα κατηγορία εμφανίζεται εδώ.
Παρόλο που ο κώδικας ορίζει ένα φορέα κάτω με floating-point συνιστώσες, το έγγραφο αυτό, επίσης, κάνει χρήση των φορέων με ακέραιος συστατικά.
Οι παρακάτω κώδικα μπορούν εύκολα να τροποποιηθούν για να υλοποιήσουν φορείς με ακέραιος συστατικά.
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) διαστάσεων μηδέν φορέα:" Ένας φορέας με όλες τις συνιστώσες (d) ίση με μηδέν.
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) διαστάσεων χώρο: σημεία
"(d) διαστάσεων διαστημικό σημείο:" Μια σειρά από μεταβλητές (d) με ειδικές τιμές "(τιμές συντονίσουν)."
"(d) διαστάσεων χώρο προέλευσης:" Μια σειρά από μεταβλητές (d) με όλες τις τιμές ίσες με το μηδέν.
3.6 (d) διαστάσεων φορέων: μη σχετικό και σχετική
Μια (d) διαστάσεων φορέα που "δεν" είναι "σχετική" είναι μια (d) διαστάσεων φορέων που άμεσα ή αντιπροσωπεύει ένα καθεστώς ρύθμισης.
Μια (d) διαστάσεων φορέα που είναι "σχετικό" είναι ένα (d) διαστάσεων φορέα που εκπροσωπεί τις αλλαγές σε ένα σύνολο στοιχείων.
Ένα σχετικό φορέα μπορεί να αντιπροσωπεύει τη διαφορά μεταξύ δύο μη σχετικούς φορείς.
Λαμβάνοντας υπόψη ένα σχετικό φορέα, για τον καθορισμό ενός μη σχετική ιδιότητα ή την ρύθμιση της χρησιμοποίησης του εν λόγω φορέα απαιτεί σχετική συνδυάζει τη σχετική με φορέα μη σχετικό φορέα.
Μη σχετική φορείς σχετικούς φορείς και οι δύο φορείς.
Είτε ένα συγκεκριμένο φορέα είναι μη συγγενής ή σχετική πρέπει να προσδιορίζεται κατά τις οποίες ο φορέας έχει οριστεί.
Εάν ένα (d) διαστάσεων φορέας ερμηνεύεται ως μη σχετική, τότε η (d) διαστάσεων φορέα μπορεί να αντιπροσωπεύει ένα σημείο στο (d) διαστάσεων χώρο.
3.7 (d) διαστάσεων φορέα Επιπλέον, η αφαίρεση, και την κλιμάκωση
Vector Επιπλέον, η αφαίρεση, και την κλιμάκωση:
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) διαστάσεων βάση διανυσμάτων
Ο επίσημος ορισμός της "βάσης" του φορέα διάστημα:
Ας (T) να είναι ένας βασικός τύπος (παραδείγματα: πραγματικός αριθμός, ακέραιος, αριθμός πολύπλοκων, ορθολογική αριθμό, κλπ).
Κάθε μεταβλητή του βασικού τύπου ονομάζεται "μονοδιάστατη."
Ας (V) είναι "(T) τύπου (d) διαστάσεων διανυσματικό χώρο."
Εάν η μη μηδενική φορέων { u1, u2, ..., ud } στο (V) είναι τέτοια ώστε κάθε φορέας (v) στο (V) μπορεί να γραφτεί ως ένα "γραμμικό συνδυασμό" των εν λόγω φορέων, v = c1*u1 + c2*u2 + ... + cd*ud, όπου { c1, c2, ..., cd } είναι scalars του τύπου (T), τότε είναι (V) "βαθμονομείται" με φορείς { u1, u2, ..., ud }.
Οποιοδήποτε σύνολο των μη μηδενικών διανυσμάτων { u1, u2, ..., ud } που "εκτείνονται σε" διανυσματικό χώρο (V) ονομάζεται "βάση" (V).
Μια απλή "βάση" μια (d) διαστάσεων διανυσματικό χώρο είναι το σύνολο των (d) διακριτή (d) διαστάσεων φορείς, με κάθε ένα στοιχείο ίσο με ένα και όλα τα άλλα στοιχεία που ισούται με μηδέν.
Οι εν λόγω φορείς είναι "orthonormal" βάση, σημαίνει ότι έχουν αμοιβαία κάθετα "(ορθογώνια)" και ότι κάθε φορέας έχει μονάδα μήκους.
Κάθε τέτοιος φορέας είναι φορέας μιας μονάδας παράλληλη προς μια από τις (d) συντονίζουν άξονες.
Εκφράζοντας μια αυθαίρετη φορέα ως ένα "γραμμικό συνδυασμό" αυτών των φορέων είναι η άμεση βάση? Κάθε στοιχείο του αυθαίρετου φορέα πολλαπλασιάζεται με την αντίστοιχη βάση του φορέα, καθώς και τα προϊόντα αυτά να προστεθούν μαζί για να σχηματίσουν την αυθαίρετη φορέα.
Ο κώδικας που ακολουθεί δείχνει πώς ένας φορέας μπορεί να εκφραστεί ως ένα "γραμμικό συνδυασμό" των φορέων βάση.
Οι παρακάτω κώδικα αυθαίρετα ορίζει ως βάση orthonormal σειρά φορέων.
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 )
// . . .
}
}
Κάθε φορέας στον (d) διαστάσεων χώρος μπορεί να εκφραστεί ως άθροισμα των προϊόντων βάση των αριθμών και των φορέων:
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) διαστάσεων χώρο: την απόσταση μεταξύ των σημείων
Ας (P) είναι (d) διαστάσεων φορέα που αντιπροσωπεύει ένα σημείο στο (d) διαστάσεων χώρο.
Ας (Q) είναι (d) διαστάσεων φορέα που αντιπροσωπεύει ένα σημείο στο (d) διαστάσεων χώρο.
Ας (R) είναι (d) διαστάσεων φορέα που αντιπροσωπεύει τη μεταβολή (d) συντεταγμένες για να φτάσετε από το σημείο (P) σε σημείο (Q)? R = (Q - P).
Σε ένα χώρο διαστάσεων, P = ( p0 ), Q = ( q0 ), και R = (Q - P) = ( q0 - p0 ).
Η απόσταση μεταξύ των δύο σημείων είναι: Abs( q0 - p0 ).
Σε δισδιάστατο χώρο, P = ( p0, p1 ), Q = ( q0, q1 ), και R = (Q - P) = ( q0-p0, q1-p1 ).
Ερμηνεύοντας τις δύο κάθετες μετατοπίσεις όπως το κάθετο πλευρές του τριγώνου δεξιά, η απόσταση μεταξύ των σημείων αντιστοιχεί στο μήκος του hypotenuse αυτού του τριγώνου.
Η Pythagorean τύπος, (a*a) + (b*b) = (c*c), όπου (a) και (b) είναι το μήκος της καθέτου πλευρές ενός τριγώνου δεξιά, και (c) είναι το μήκος του hypotenuse (skew πλευρά), μπορεί να χρησιμοποιηθεί για να καθοριστεί η απόσταση μεταξύ των δύο σημείων: Sqrt( Sq(q0-p0) + Sq(q1-p1) ).
Στο τρισδιάστατο χώρο, P = ( p0, p1, p2 ), Q = ( q0, q1, q2 ), και R = (Q - P) = ( q0-p0, q1-p1, q2-p2 ).
Ερμηνεύοντας τον εκτοπισμό ( q0-p0, q1-p1, 0 ) όπως το κάθετο πλευρές του τριγώνου δεξιά, και χρησιμοποιώντας τον τύπο Pythagorean, δίνει η απόσταση μεταξύ του σημείου (P) και το σημείο ( q0, q1, p2 ): d01 = Sqrt( Sq(q0-p0) + Sq(q1-p1) ).
Η μετατόπιση ( q0-p0, q1-p1, 0 ) είναι κάθετος προς τον εκτοπισμό ( 0, 0, q2-p2 ), και άλλο δικαίωμα τρίγωνο μπορεί να σχηματιστεί και η Pythagorean τύπος μπορεί να χρησιμοποιηθεί ξανά.
Έτσι, η απόσταση από το σημείο (P) σε σημείο (Q) δίδεται από τη σχέση: 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) ).
Η μέθοδος της επέκτασης της απόστασης τύπος από δισδιάστατο χώρο σε τρισδιάστατο χώρο μπορεί να εφαρμοστεί κατ 'επανάληψη για να καθορίσει τελικά την απόσταση φόρμουλα για (d) διαστάσεων χώρο: Sqrt( (Sq(q0-p0) + Sq(q1-p1)) + Sq(q2-p2) + ... + Sq(qd-pd) ).
Οι παρακάτω κώδικα ορίζει μια λειτουργία που ονομάζεται "Μήκος" οποία υπολογίζει το μήκος ενός (d) διαστάσεων φορέα.
Όταν ένας φορέας εκπροσωπεί τη μετατόπιση μεταξύ δύο σημείων στο χώρο (d) διαστάσεων, το μήκος του φορέα που εκπροσωπεί την απόσταση μεταξύ των δύο αυτών σημείων.
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) διαστάσεων φορέων: dot προϊόντος
Το "προϊόν dot" μετατρέπει (d) δυο διαστάσεων σε μια σειρά φορέων.
Ο κώδικας παρακάτω υπολογίζει μια κουκίδα προϊόν των δύο φορέων:
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);
}
// . . .
}
Για κάθε φορέα, (A), Length(A) = Sqrt(Dot(A,A)).
3.11 (d) διαστάσεων φορέων: ορισμός της "παράλληλης"
Διανύσματα (A) και (B) είναι "παράλληλες," αν όλα τα ακόλουθα είναι αληθές:
(1) A.Length() > 0?
(2) B.Length() > 0?
(3) Abs(Dot(A,B)) = A.Length()*B.Length().
Οι παρακάτω κώδικα καθορίζει εάν ένα ζεύγος διανυσμάτων είναι παράλληλες (πιθανώς αντι-ευθυγραμμισμένο).
Floating-point αριθμών μπορούν να συσσωρεύουν λάθη στο κλασματικό μέρος, λόγω της περιορισμένης ακρίβειας, και, ως εκ τούτου, θα πρέπει να περιλαμβάνουν κώδικα υπολογιστή μη μηδενικές ανοχές κατά τη σύγκριση floating-point αριθμών.
Ο κώδικας περιλαμβάνει π.χ. τις αξίες της ανοχής, αλλά το παράδειγμα αξίες της ανοχής μπορεί να μην είναι κατάλληλο για ορισμένα καθήκοντα.
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) διαστάσεων φορέων: ορισμός της "καθέτου"
Διανύσματα (A) και (B) είναι "κάθετα" αν όλα τα ακόλουθα είναι αληθές:
(1) A.Length() > 0?
(2) B.Length() > 0?
(3) Abs(Dot(A,B)) = 0.
Οι παρακάτω κώδικα καθορίζει εάν ένα ζεύγος φορέων είναι κάθετος. Floating-point αριθμών μπορούν να συσσωρεύουν λάθη στο κλασματικό μέρος, λόγω της περιορισμένης ακρίβειας, και, ως εκ τούτου, θα πρέπει να περιλαμβάνουν κώδικα υπολογιστή μη μηδενικές ανοχές κατά τη σύγκριση floating-point αριθμών.
Ο κώδικας περιλαμβάνει π.χ. τις αξίες της ανοχής, αλλά το παράδειγμα αξίες της ανοχής μπορεί να μην είναι κατάλληλο για ορισμένα καθήκοντα.
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 Πίνακες
"matrix:" Μια συλλογή από μεταβλητές τέτοιες ώστε κάθε μεταβλητή έχει ένα μοναδικό συνδυασμό μιας "σειράς" όνομα και ένα όνομα "στήλης."
"entry:" Μια μεταβλητή μ