Trigonométrie matricielle


13

introduction

Les deux fonctions trigonométriques les plus courantes, sineet cosine(ou sinetcos pour faire court), peuvent être étendues pour être des fonctions matricielles. Une façon de calculer les analogues à valeurs matricielles est la suivante:

Considérez ces deux identités trigonométriques importantes:

identités trigonométriques

En utilisant ces identités, nous pouvons dériver les équations suivantes pour sinet cos:

fonctions trigonométriques

L' exponentielle de matrice existe pour toutes les matrices carrées et est donnée par:

matrice exponentielle

A 0 est la matrice d'identité I avec les mêmes dimensions que A . En utilisant l'exponentielle matricielle, ces deux fonctions trigonométriques (et donc toutes les autres fonctions trigonométriques) peuvent être évaluées comme des fonctions de matrices.

Le défi

Étant donné une matrice carrée A , affichez les valeurs de sin(A)et cos(A).

Règles

  • L'entrée et la sortie peuvent être dans n'importe quel format pratique et raisonnable (tableau 2D, format matriciel de votre langue, etc.).
  • Vous pouvez écrire un seul programme, deux programmes indépendants, une seule fonction ou deux fonctions. Si vous choisissez d'écrire deux fonctions, le code peut être partagé entre elles (telles que les importations et les fonctions d'assistance).
  • Les valeurs de la matrice d'entrée seront toujours des entiers.
  • Votre solution peut présenter des problèmes de précision en raison d'une imprécision en virgule flottante. Si votre langue avait des valeurs magiques de précision infinie, alors votre solution devrait fonctionner parfaitement (en ignorant le fait qu'elle nécessiterait un temps infini et / ou de la mémoire). Cependant, comme ces valeurs magiques de précision infinie n'existent pas, les inexactitudes causées par une précision limitée sont acceptables. Cette règle est en place pour éviter les complications résultant de la nécessité d'une précision spécifique dans la sortie.
  • Les commandes internes qui calculent des fonctions trigonométriques pour les arguments de matrice (y compris les fonctions trigonométriques hyperboliques) ne sont pas autorisées. D'autres matrices intégrées (telles que la multiplication, l'exponentiation, la diagonalisation, la décomposition et l'exponentielle de la matrice) sont autorisées.

Cas de test

Format: A -> sin(A), cos(A)

[[0]] -> [[0]], [[1]]
[[0, 2], [3, 5]] -> [[-0.761177343863758, 0.160587281888277], [0.240880922832416, -0.359709139143065]], [[0.600283445979886, 0.119962280223493], [0.179943420335240, 0.900189146538619]]
[[1, 0, 1], [0, 0, 0], [0, 1, 0]] -> [[0.841470984807897, -0.158529015192103, 0.841470984807897], [0, 0, 0], [0, 1, 0]], [[0.540302305868140, -0.459697694131860, -0.459697694131860], [0, 1, 0], [0, 0, 1]]
[[1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 0, 1]] -> [[0.841470984807897, 0, 0, 0, 0], [0, 0.841470984807897, 0, 0, 0], [0, 0, 0.841470984807897, 0, 0], [0, 0, 0, 0.841470984807897, 0], [0, 0, 0, 0, 0.841470984807897]], [[0.540302305868140, 0, 0, 0, 0], [0, 0.540302305868140, 0, 0, 0], [0, 0, 0.540302305868140, 0, 0], [0, 0, 0, 0.540302305868140, 0], [0, 0, 0, 0, 0.540302305868140]]
[[-3, 2, -6], [3, 0, 4], [4, -2, 7]] -> [[-0.374786510963954, 0.135652884035570, -1.35191037980742], [1.14843105375406, 0.773644542790111, 1.21625749577185], [1.21625749577185, -0.135652884035570, 2.19338136461532]], [[4.13614256031450, -1.91289828483056, 5.50873853927692], [-2.63939111203107, 1.49675144828342, -3.59584025444636], [-3.59584025444636, 1.91289828483056, -4.96843623340878]]

Lectures complémentaires

Cette excellente question de Math.SE comprend des dérivations alternatives des analogues matriciels des fonctions trigonométriques.


Je suis arrivé sin([[1, 0, 1], [0, 0, 0], [0, 1, 0]]) = {{0.841, -0.158, 0.841}, {0, 0, 0}, {0, 1, 0}}avec Mathematica, pouvez-vous vérifier?
kennytm

1
@kennytm C'est ce que montre le scénario de test.
Mego

1
@Mego Apparemment, toutes les réponses existantes devraient alors être supprimées.
feersum

3
@Mego Il est tout à fait déraisonnable de penser que tous les modules intégrés basés sur des virgules flottantes utilisent un algorithme exact (ou un algorithme qui serait exact si les opérations en virgule flottante étaient remplacées par des opérations en "nombre réel").
feersum

1
@feersum Je l'ai abordé dans ma dernière édition:(ignoring the fact that it would require infinite time and/or memory)
Mego

Réponses:


6

Julia, 33 19 octets

A->reim(expm(A*im))

Il s'agit d'une fonction qui accepte un tableau à deux dimensions de flotteurs et renvoie un tuple de ces tableaux correspondant respectivement au cosinus et au sinus. Notez qu'il s'agit de l'inverse de l'ordre donné dans les cas de test, dans lequel le sinus est répertorié en premier.

Pour une matrice A à valeur réelle , nous avons

sinus

et

cosinus

C'est-à-dire que le sinus et le cosinus de A correspondent aux parties imaginaires et réelles de la matrice exponentielle e iA . Voir Fonctions des matrices (Higham, 2008).

Essayez-le en ligne! (inclut tous les cas de test)

Enregistré 14 octets grâce à Dennis!


6

Mathematica, 27 octets

{Im@#,Re@#}&@MatrixExp[I#]&

Basé sur la solution de @ Rainer P.

Prend la matrice carrée Acomme argument et génère une liste contenant {sin(A), cos(A)}.

L'entrée est formatée avec Npour obtenir une valeur numérique au lieu d'une longue formule exacte et Columnpour afficher les résultats de sin(A)et en cos(A)tant que matrices distinctes au lieu d'une liste imbriquée.

Exemple

Le calcul des valeurs séparément nécessite 38 octets

{(#2-#)I,+##}/2&@@MatrixExp/@{I#,-I#}&

6

Gelée , 23 22 octets

³æ*÷!
®Ḥ‘©r0Ç€s2_@/µÐL

Essayez-le en ligne!

Contexte

Cette approche calcule directement la série de Taylor pour le sinus et le cosinus , c.-à-d.

formule

Il augmente le nombre de termes initiaux des deux séries jusqu'à ce que le résultat ne change plus, de sorte que sa précision n'est limitée que par la précision du type à virgule flottante.

Comment ça fonctionne

®Ḥ‘©r0Ç€s2_@/µÐL  Main link, Argument: A (matrix)

             µÐL  Loop; apply the chain until the results are no longer unique.
                  Return the last unique result.
®                   Yield the value of the register (initially zero).
 Ḥ                  Unhalve/double it.
  ‘©                Increment and copy the result (n) to the register.
    r0              Range; yield [n, ..., 0].
      ǀ            Apply the helper link to each k in the range.
        s2          Split the results into chunks of length 2. Since n is always
                    odd, this yields [[Ç(n), Ç(n-1)], ..., [Ç(1), Ç(0)]].
          _@/       Reduce the columns of the result by swapped subtraction,
                    yielding [Ç(1) - Ç(3) + ... Ç(n), Ç(0) - Ç(2) + ... Ç(n - 1)].


³æ*÷!             Helper link. Argument: k (integer)

³                 Yield the first command-line argument (A).
 æ*               Elevate A to the k-th power.
    !             Yield the factorial of k.
   ÷              Divide the left result by the right one.

2

Matlab, 138 121 52 50 octets

Puisque l'exponentiation matricielle est autorisée, (ce que je n'ai pas remarqué en premier, d'oh) je n'ai plus besoin de définir ma fonction d'aide, et le tout peut être résolu de manière triviale:

A=input('')*i;a=expm(A);b=expm(-A);[(b-a)*i,a+b]/2

L'entrée doit être une matrice, par exemple [1,2;4,5]ou alternativement[[1,2];[3,4]]

Une chose inattendue (avec le recul pas si inattendu) est que la matrice cosinus et sinus satisfait toujours

I = sin(A)^2+cos(A)^2

N'est-ce pas A^0la même chose que eye(size(A))?
FryAmTheEggman

Oh, tu as raison, merci!
flawr

2
Pourquoi ne pas utiliser expm?
Luis Mendo

2
Selon l'identité: j'espère qu'ils satisfont cette identité, étant donné que la forme scalaire a été utilisée pour étendre les fonctions aux matrices!
Mego

1
Eh bien, le tout devient presque trivial.
flawr


2

C ++, 305 octets

#include<cmath>
#include<iostream>
#include<vector>
int x,i=0, j;void p(std::vector<double> v){int x=sqrt(v.size());for(i=0;i<x;i++){for(j=0;j<x;j++) std::cout << v[x] << " ";std::cout << "\n";}}int main(){std::vector<double> s, c;while(std::cin >> x){s.push_back(sin(x));c.push_back(cos(x));}p(s);p(c);}

L'entrée est une liste de nombres qui sont un carré parfait sur stdin. La sortie est un joli tableau 2D imprimé sur stdout


0

Julia 0.4, 28 octets

A->imag({E=expm(im*A),im*E})

L'entrée est une matrice de flottants, la sortie est un tableau de matrices. Essayez-le en ligne!


0

Sauge, 44 octets

lambda A:map(exp(I*A).apply_map,(imag,real))

Essayez-le en ligne .

Cette fonction anonyme renvoie une liste de 2 matrices correspondant respectivement à sin(A)et cos(A). exp(I*A)calcule l'exponentielle de la matrice pour I*A( Aavec tous les éléments multipliés par l'unité imaginaire) et matrix.apply_map(f)renvoie une matrice où fa été appliquée à tous ses éléments. En appliquant imaget real(les fonctions pour obtenir les parties imaginaires et réelles d'une valeur scalaire) aux matrices, nous obtenons les valeurs de sin(A)et cos(A), grâce à la célèbre identité d'Euler (référencée dans le texte du défi).

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.