English  Español  Português  Français  Italiano  Deutsch  Nederlands  Svenska  Dansk  Suomi  Norsk  Русский  Polski  Română  Български  Hrvatski  Česky  中国  中國  日本語  한국어  Ελληνική  हिन्दी  العربية 
Álgebra Linear
Colin Fahey

1. Software

LinearAlgebra.zip
Álgebra Linear código fonte (C#)
19910 bytes
MD5: 11d8c8035cac30ba543e5e0b72ee9767

2. Introdução

Este artigo descreve vetores e matrizes, em (d)-dimensional espaço.

3. (d)-dimensional espaço: atributos

3.1 Array

“array:” Uma coleção de variáveis de modo a que cada variável tem um nome único, e de tal modo que os nomes podem ser atribuídos um fim.
Valores inteiros podem ser usadas como nomes para as variáveis em um array.
Por exemplo, se um array contém (d) variáveis e, em seguida, os valores inteiros { 0, 1, 2, ..., (d-1) } os nomes podem ser atribuídos às variáveis do array.

3.2 (d)-dimensional vector

(d)-dimensional vector:” Um conjunto de variáveis (d).
“vetor componente:” Uma variável dentro de um vector.

3.3 (d)-dimensional vector espacial

“one-dimensional espaço:” O conjunto completo de valores que podem ser armazenados em uma variável.
(d)-dimensional espaço:” O conjunto completo de combinações de valores que podem ser armazenadas em um array de (d) variáveis.
A definição formal de um “espaço vetorial:”
Deixe (T) ser um tipo básico (exemplos: número real, inteiro, número complexo, número racional, etc).
Qualquer uma variável do tipo básico é nomeado um “escalar.”
Um “(T)-tipo (d)-dimensional vector espaço” é o conjunto (S) de (d)-dimensional vetores ter duas operações, além (+) vetorial, escalar e multiplicação (*), satisfazendo as condições abaixo:
(1) Se (v) e (w) são quaisquer dois vectores em (S) e, em seguida, (v + w) é também um vector de (S);
(2) Se (u), (v), e (w) são três vectores, em qualquer (S) e, em seguida, (u + v) + w = u + (v + w);
[aditivo Comutatividade]
(3) Se (v) e (w) são quaisquer dois vectores em (S) e, em seguida, (v + w) = (w + v);
[aditivo associatividade]
(4) Existe um “vetor zero,” (0), em (S), de tal forma que para qualquer vector (v) em (S), (v + (0)) = v;
[aditivo identidade]
(5) Se (c) é qualquer tipo de escalar (T), e (v) é qualquer vetor em (S) e, em seguida, o produto (c * v) é um vetor em (S);
(6) Se (a), (b), e (c) são escalares de qualquer tipo (T), e (v) e (w) são vetores em qualquer (S) e, em seguida, (a + b) * v = a*v + b*v, e c*(v + w) = c*v + c*w;
[multiplicativo distributivity]
(7) Se (a) e (b) são escalares de qualquer tipo (T), e (v) é qualquer vetor em (S) e, em seguida, (a*b)*v = a*(b*v);
(8) Se “1” é um tipo de escalar (T) tal que (1*1)=1, e (v) é qualquer vetor em (S) e, em seguida, (1*v) = v;
(9) Para cada vector (v) em (S), o vetor (-1)*v = -v satisfaz v + (-v) = (0);
[aditivo inversa]

3.4 (d)-dimensional vector código

O código abaixo mostra como um vetor (d)-dimensional, com 64 bits de ponto flutuante de componentes, pode ser implementada.
Um array é suficiente para representar um vetor.
O código abaixo tem um array contidos em uma classe, apenas por conveniência.
O código não se destina a ser eficientes.
Uma estrutura (exemplo: “struct”, um tipo de valor), representando vetores de um número fixo de dimensões (exemplos: 3 ou 4) é provável que seja muito mais eficiente do que a geral (d)-dimensional vector classe mostrado aqui.
Apesar de o código abaixo define um vetor com componentes de ponto flutuante, este documento também faz uso de vetores com componentes inteiro.
O código abaixo pode ser facilmente modificado para implementar vetores com componentes inteiro.
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 VectorF64params 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 VectorF64VectorF64 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 VectorF640.01.02.0 );
        v3.WriteLine(); // ( 0, 1, 2 )

        // A 4-dimensional vector with 64-bit floating-point components:
        VectorF64 v4 = new VectorF640.01.02.03.0 );
        v4.WriteLine(); // ( 0, 1, 2, 3 )

        // . . .
    }
}
(d) zero-dimensional vector:” Um vetor com todos os componentes (d) igual 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)-dimensional espaço: pontos

(d)-dimensional espaço ponto:” um arranjo de (d) variáveis com valores específicos “(valores coordenar).”
(d)-dimensional espaço origem:” um arranjo de (d) todas as variáveis com valores iguais a zero.

3.6 (d)-dimensional vectores: não-parente e parente

Um (d)-dimensional vector que “não” é “parente” é um vetor (d)-dimensional que representa directamente a um estatuto ou configuração.
Um (d)-dimensional vector que é “relativa” (d)-dimensional é um vetor que representa a evolução de um conjunto de componentes.
Um parente vetor pode representar a diferença entre os dois vetores não-parente.
Dado um parente vetor, determinando um estado não-parente ou configuração usando esse parente vetor exige que combinam com um parente vetor não-parente vetor.
Não-parente vetores e relativos são vetores dois vectores.
Se um determinado vetor é não-familiar ou parente deve ser especificado quando o vector está definido.
Se um (d)-dimensional vector é interpretado como sendo não-parente, então o (d)-dimensional vector pode representar um ponto no espaço (d)-dimensional.

3.7 (d)-dimensional vector adição, subtração, e escamação

Vector adição, subtração, e escamação:
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 VectorF640.01.02.03.0 );
        a.WriteLine(); // ( 0, 1, 2, 3 )
        VectorF64 b = new VectorF643.02.01.00.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 base vetores

A definição formal de uma “base” de um espaço vetorial:
Deixe (T) ser um tipo básico (exemplos: número real, inteiro, número complexo, número racional, etc).
Qualquer uma variável do tipo básico é nomeado um “escalar.”
Deixe (V) ser um “(T)-tipo (d)-dimensional vector espaço.”
Se o não-zero vetores { u1, u2, ..., ud } em (V) são de tal ordem que cada vector (v) em (V) pode ser escrito como uma “combinação linear” desses vetores, v = c1*u1 + c2*u2 + ...  + cd*ud, onde estão { c1, c2, ..., cd } escalares do tipo (T) e, em seguida, (V) é “calibrado” por vetores { u1, u2, ..., ud }.
Qualquer conjunto de vetores não-zero { u1, u2, ..., ud } que “abrangem” espaço (V) vetor é chamado de uma “base” de (V).
Uma simples “função” de um espaço vetorial (d)-dimensional é o conjunto de (d) distintas (d)-dimensional vetores, cada um com um elemento igual a um e de todos os outros componentes igual a zero.
Essas são vetores “orthonormal” base, o que significa que eles são mutuamente “perpendiculares-(ortogonais),” e que cada vector tem unidade de comprimento.
Cada um desses vetores é um vetor unitário paralelo a um dos eixos (d) coordenar.
Expressando um vector arbitrário como uma “combinação linear” destes vetores base é direta; cada componente do vetor arbitrário é multiplicado pela correspondente base vetorial, e esses produtos são acrescentados juntos para formar o vetor arbitrário.
O código abaixo mostra como um vetor pode ser expresso como uma “combinação linear” dos vetores base.
O código abaixo arbitrariamente orthonormal define um conjunto de vetores 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( 40 );
        b0.WriteLine(); // ( 1, 0, 0, 0 )

        VectorF64 b1 = VectorF64.BasisVector( 41 );
        b1.WriteLine(); // ( 0, 1, 0, 0 )

        VectorF64 b2 = VectorF64.BasisVector( 42 );
        b2.WriteLine(); // ( 0, 0, 1, 0 )

        VectorF64 b3 = VectorF64.BasisVector( 43 );
        b3.WriteLine(); // ( 0, 0, 0, 1 )


        // . . .
    }
}
Qualquer vetor em (d)-dimensional espaço pode ser expressa como uma soma de produtos a base de números e vetores:
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 VectorF640.11.12.23.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( 40 )
            + 1.1 * VectorF64.BasisVector( 41 )
            + 2.2 * VectorF64.BasisVector( 42 )
            + 3.3 * VectorF64.BasisVector( 43 );
        vb.WriteLine(); // ( 0.1, 1.1, 2.2, 3.3 )


        // . . .
    }
}

3.9 (d)-dimensional espaço: distância entre os pontos

Deixe (P) ser um vector (d)-dimensional que representa um ponto no espaço (d)-dimensional.
Deixe (Q) ser um vector (d)-dimensional que representa um ponto no espaço (d)-dimensional.
Deixe (R) ser um (d)-dimensional vector que representa a mudança na (d) coordenadas para chegar ao ponto de (P) ponto (Q); R = (Q - P).
Em um espaço de dimensão, P = ( p0 ), Q = ( q0 ), e R = (Q - P) = ( q0 - p0 ).
A distância entre os dois pontos é a seguinte: Abs( q0 - p0 ).
Em duas dimensões espaciais, P = ( p0, p1 ), Q = ( q0, q1 ), e R = (Q - P) = ( q0-p0, q1-p1 ).
Interpretando as duas perpendicular deslocamentos como a perpendicular lados de um triângulo de direita, a distância entre os pontos corresponde ao comprimento da hipotenusa desse triângulo.
A fórmula Pythagorean, (a*a) + (b*b) = (c*c), onde (a) e (b) são os comprimentos dos lados de uma perpendicular à direita-triângulo, e (c) é o comprimento da hipotenusa (deforme lado), podem ser utilizados para determinar a distância entre os dois pontos: Sqrt( Sq(q0-p0) + Sq(q1-p1) ).
No espaço tridimensional, P = ( p0, p1, p2 ), Q = ( q0, q1, q2 ), e R = (Q - P) = ( q0-p0, q1-p1, q2-p2 ).
Interpretando o deslocamento ( q0-p0, q1-p1, 0 ) como a perpendicular lados de um triângulo de direita, e usando a fórmula Pythagorean, dá a distância entre o ponto a ponto (P) e ( q0, q1, p2 ): d01 = Sqrt( Sq(q0-p0) + Sq(q1-p1) ).
O deslocamento ( q0-p0, q1-p1, 0 ) é perpendicular ao deslocamento ( 0, 0, q2-p2 ), e outro de direita triângulo pode ser formada, e os Pythagorean fórmula pode ser usado novamente.
Assim, a distância do ponto (P) ao ponto (Q) é dada por: 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) ).
O método de extensão a distância fórmula de duas dimensões do espaço a espaço tridimensional pode ser aplicado repetidamente para, eventualmente, determinar a distância fórmula para (d)-dimensional espaço: Sqrt( (Sq(q0-p0) + Sq(q1-p1)) + Sq(q2-p2) + ...  + Sq(qd-pd) ).
O código abaixo define uma função que calcula o chamado “Comprimento” comprimento de um vetor (d)-dimensional.
Quando um vetor representa o deslocamento entre dois pontos em (d)-dimensional espaço, o comprimento do vetor representa a distância entre esses dois pontos.
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 VectorF640.01.02.03.04.05.0 );
        p.WriteLine(); // ( 0, 1, 2, 3, 4, 5 )

        // A 6-dimensional vector representing a point (q):
        VectorF64 q = new VectorF64-5.04.0-3.02.0-1.00.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 vetores: produto escalar

O “produto escalar” converte-dimensional (d) dois vetores de um número.
O código abaixo calcula um produto escalar de dois vectores:
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);
    }




    // . . .
}
Para qualquer vector, (A), Length(A) = Sqrt(Dot(A,A)).

3.11 (d)-dimensional vectores: definição do “paralelo”

Vetores (A) e (B) são “paralelos” se todas as seguintes são verdadeiras:
(1) A.Length() > 0;
(2) B.Length() > 0;
(3) Abs(Dot(A,B)) = A.Length()*B.Length().
O código abaixo determina se um par de vetores são paralelos (possivelmente anti-alinhados).
Números de ponto flutuante pode acumular erros no fracionário parte devido à precisão limitada, e, portanto, deve incluir código computador diferente de zero quando se comparam as tolerâncias de ponto flutuante de números.
O código inclui exemplo tolerância valores, mas o exemplo tolerância valores poderá não ser apropriado para algumas tarefas.
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 VectorF640.01.02.03.04.05.0 );
        vf.WriteLine(); // ( 0, 1, 2, 3, 4, 5 )

        // A 6-dimensional vector:
        VectorF64 vg = new VectorF640.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 vectores: definição de “perpendicular”

Vetores (A) e (B) são “perpendiculares” se todas as seguintes são verdadeiras:
(1) A.Length() > 0;
(2) B.Length() > 0;
(3) Abs(Dot(A,B)) = 0.
O código abaixo determina se um par de vetores são perpendiculares.  Números de ponto flutuante pode acumular erros no fracionário parte devido à precisão limitada, e, portanto, deve incluir código computador diferente de zero quando se comparam as tolerâncias de ponto flutuante de números.
O código inclui exemplo tolerância valores, mas o exemplo tolerância valores poderá não ser apropriado para algumas tarefas.
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 VectorF640.01.02.00.04.05.0 );
        vf2.WriteLine(); // ( 0, 1, 2, 0, 4, 5 )

        // A 6-dimensional vector:
        VectorF64 vg2 = new VectorF6410.00.00.0-5.00.00.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 Matrizes

“matriz:” Uma coleção de variáveis de modo a que cada variável tem uma combinação única de uma “linha” e uma “coluna” nome nome.
“entrada:” uma variável dentro de uma matriz.
Valores inteiros podem ser usadas como nomes “fila” e “coluna” nomes para as variáveis em uma matriz.
Por exemplo, se uma matriz tem (totalRows) linhas e colunas (totalColumns), então os valores inteiros { 0, 1, ..., (totalRows-1) } pode ser o nome atribuído às fileiras, e os valores inteiros { 0, 1, ..., (totalColumns-1) } podem ser os nomes atribuídos às colunas.
Assim, uma variáveis em uma matriz pode ser especificado pela especificação de um par de inteiros, ( row, column ), indicando a combinação dos índices linha e coluna correspondente à variável específica.
O tamanho de uma matriz é especificada como “(totalRows) * (totalColumns)” (ou “(totalRows) por (totalColumns)).”
Este fim de dimensões é a mesma que a ordem das dimensões usadas para especificar as entradas na matriz “(( row, column )).”
[Esta convenção é um pouco infeliz, porque para muitos usos bidimensional (exemplos: imagens, gráficos, etc) é o habitual convenção para especificar as dimensões “width * height” e coordena as “( horizontal, vertical )” (ou “( x, y )).”
Este é o oposto da ordem de dimensões e coordenadas usado para descrever matrizes e os seus cadastros.  ]
Uma matriz com (totalRows) igual a (totalColumns) é chamado “quadrado;” de outra forma, a matriz é chamado “retangular.”
A matriz pode ser considerada como contendo um conjunto de “vetores linha,” onde as variáveis em cada linha são interpretados como pertencentes a um vetor.
Uma matriz também pode ser considerado como contendo um conjunto de “vetores coluna,” onde as variáveis em cada coluna são interpretadas como pertencentes a um vetor.
Matrizes podem representar uma grande variedade de relações matemáticas.
O significado de uma matriz, e as operações que possam ser apropriadas para a transformação entradas de uma matriz, depende do contexto.
No entanto, existem regras básicas de aritmética matriz que sejam relevantes para muitos contextos, e estas regras básicas será definido em uma seção posterior.
Um array e um valor (totalColumns) são suficientes para representar uma matriz.
A matriz pode ter (totalRows * totalColumns) variáveis, e da entrada em ( row, column ) pode corresponder à matriz a variável Índice ((totalColumns * row) + column).
O código abaixo define uma matriz, com 64 bits de ponto flutuante de entradas.
Um array e um valor (totalColumns) são suficientes para representar uma matriz.
O código abaixo tem um array e um (totalColumns) valor contido em uma classe, apenas por conveniência.
O código abaixo não se destina a ser eficientes.
Uma estrutura (exemplo: “struct”, um tipo de valor), representando matrizes de especial dimensões fixas (exemplos: 2*2, 3*3, ou 4*4) é provável que seja muito mais eficiente do que a classe geral (totalRows * totalColumns) mostrado aqui.