[Maths] Simplification d'équation

@Tristan.T : Je n’avais pas compris que cette formule correspondait à ça. Peux-tu la blinder de parenthèses s’il-te-plaît ? Car moi je la comprends ainsi :

Et quand je la trace sur un graphique avec kmplot, elle n’est pas bonne (ça doit être un problème de parenthèses).


Pour ton programme, je l’ai réécrit en C en corrigeant les erreurs d’initialisation. Il fonctionne bien. Voici la version en C :

[code]#include <stdio.h>
#include <stdlib.h>
#include <math.h>

long double carre(long double x) {
return x*x;
}

long double mon_arcsinus(long double x, long m) {
long n = 0;
long double n_factoriel = 1;
long double deux_n_factoriel = 1;
long double deux_puissance_n = 1;
long double x_puissance_2n_plus_1 = x;

long double angle = 0;

do {
angle += (deux_n_factorielx_puissance_2n_plus_1) / (carre(deux_puissance_n * n_factoriel) * (2n+1));
++n;
n_factoriel = n;
deux_n_factoriel = (2n) * (2
n - 1);
deux_puissance_n *= 2;
x_puissance_2n_plus_1 *= x * x;
} while (n <= m);

return angle;
}

int main(int argc, char ** argv) {
long double x = strtold(argv[1], NULL); //1er argument : valeur du sinus
long m = strtol(argv[2], NULL, 10); //2eme argument : precision

long double angle = mon_arcsinus(x, m);

printf("%.30Lf (sinus passe en argument)\n", x);
printf("%.30Lf (arcsinus prédéfini)\n", asinl(x));
printf("%.30Lf (angle calculé)\n", angle);
printf("%.30Lf (différence entre les angles)\n", asinl(x) - angle);
return EXIT_SUCCESS;
}[/code]

Pour le compiler, utiliser cette ligne de commande :

euh, en relisant j’ai pas trouve d’erreur de parenthèses mais je n’ai jamais été bon pour ca ^^. je mets le résultat en mode TeX

Ou, pour etre peut etre plus lisible :

u = \left(\frac{\sqrt{x^2-1}{8}-\frac{x}{8}\right)^{1/3}

y=u+1/(4u)

oui, je vien de me rendre compte que j’avais initialise les factorielles a 0 … pas bon ca mais :shhh: pas un mot a mon prof de math :wink:

Après oui j’ai laisse en pseudo-code parce que le C je l’ai un peu laisse de côté ces derniers temps au profit du Caml

Mais il manque toujours la fonction pour determiner le bon m ^^

C’est pas très grave de déterminer le bon m. Je vais arrêter la recherche ici je dois travailler sur autre chose. Merci à toi Tristan.T et aux autres !


Je mets le code en C qui correspond à la façon que j’ai trouvée en premier :

[code]#include <stdio.h>
#include <stdlib.h>
#include <math.h>

long double sinus_du_demi_angle(long double sinus) {
return sinus / sqrtl(2.0L + 2.0L * sqrtl(1.0L - sinus*sinus));
}

long double sinus_de_langle_divise_par_2_puissance_n(long double sinus, long n) {
long i;
for (i = 1; i <= n; ++i)
sinus = sinus_du_demi_angle(sinus);
return sinus;
}

long double mon_arcsinus(long double sinus, long n) {
return powl(2.0, n) * sinus_de_langle_divise_par_2_puissance_n(sinus, n);
}

int main(void) {
long double pi = acosl(-1.0L);
long double angle = pi/6.0L;
long double sinus = sinl(angle);

long double angle_obtenu = mon_arcsinus(sinus, 1000);
printf("%.40Lf (erreur en radians)\n", angle_obtenu - angle);

return EXIT_SUCCESS;
}[/code]

Bon, majorer le reste de cette série ne m’a pas l’air d’être quelque chose de trivial (si quelqu’un en a une je suis preneur du majorant et de la démonstration ^^)

Même si branch a bien préciser que de ne pas connaître l’erreur de sa fonction … moi ça me gêne un peu de calculer une valeur approchée sans pouvoir fournir une quelconque précision sur l’erreur …

Sinon j’ai eu une idée de programme calculant la fonction arcsin et pouvant fournir une erreur de la fonction.

En fait je me sert du fait que arcsin(x)=int(1/sqrt(1-x**3),t,0,x)

En effet : d(arcsin(x))/dx = 1/sqrt(1-x**2) et arcsin(0)=0

Et en partant de là on effectue un calcul approché de l’intégrale. Par exemple on peux utiliser la methode des rectangles et on dit que la valeur de notre arcsin est comprise entre la valeur donnée par les rectangles supérieures et celle donnée par les rectangles inférieurs
http://fr.wikipedia.org/wiki/Calcul_num%C3%A9rique_d%27une_int%C3%A9grale#Formules_simples

Ca nous donne ainsi un calcul de la fonction arcsin avec connaissance de l’erreur

C’est re-moi. Je me suis demandé à mon tour comment calculer la fonction cos (ou sin)

Car si ce qui a fait marcher le calcul de la fonction arcsin c’est qu’on savait calculer la dérivé de la fonction arcsin. On ne sait pas calculer la dérivée de la fonction cos qui est, je le rappelle, -sin.

On peut utiliser l’idée que j’avais eu pour donner la valuer de la fonction arcsin. En passant par un DES :

[TeX]\forall x \in \mathbb{R}, \cos(x) = \sum_{n = 0}^{+\infty} {( - 1)^n } \frac{{x^{2n} }}{{(2n)!}}[\TeX]
Si la majoration du DES de la fonction arcsin n’etait pas trivial, celui de la fonction cos est faisable et raisonnable.

En effet le DES de la fonction cos est une série alternée. On a [TeX]\left\lbrace\sum_{n = 0}^{+\infty} {( - 1)^n } \frac{{x^{2n} }}{{(2n)!}} - \sum_{n = 0}^{m} {( - 1)^n } \frac{{x^{2n} }}{{(2n)!}}\right\rbrace < \frac{{x^{2m} }}{{(2m)!}} [\TeX]

Autrement dit : On trouve le m tel que x^{2m}/(2m)! < epsilon et on a \sum_{n = 0}^{m} (-1)^n * x^{2n}/(2n)! = cos x à plus ou moins epsilon pres

J’espère avoir été clair :shifty:

Bon, mon dernier message sur ce topic ^^

Si le calcul des fonctions intéresse quelqu’un j’ai créé ce doc : http://www.mediafire.com/?qhc770mvh0r2sxb

Il n’y a rien de nouveau. Juste l’explication de ce que j’ai pu dire précédemment mais écrit en TeX :wink:

Bon, pour le cos, fais attention, x^(2n)/(2n)! n’est pas décroissant au début mais seulement à partir d’un certain rang (trouve lequel).

Pour arcsin, la méthode de calcul de z(n)=2^n.sin(x/2^n) est plutôt bonne je trouve et plus efficace que le calcul de l’intégrale.
En posant y(n)=z(n)^2, tu obtiens respectivement

y(n+1)=24^n(1-racine(1-y(n)/4^n))

et y(n+1) = y(n)+y(n)²/4^(n+1)+O(y(n)^3) ce qui t’assure une vitesse de convergence linéaire en le nombre de décimales voulues (i.e coût constant d’une décimale). Dans la pratique, y(n+1)-y(n) te donne l’ordre de grandeur de la précision atteinte donc. La valeur que tu cherches est racine(y(n)).
Teste sur openoffice, tu verras que le calcul de 10 termes suffit.

La série entière n’est pas la panacée pour cos, tu peux trouver mieux, je te laisse chercher.

un = x^(2n)/(2n)!

u_(n+1)/un = (x^(2n+2)(2n)!)/((2n+2)!x^(2n)) = x^2/((2n+1)(2n+2))

Il suffit d’avoir de trouver n a partir duquelle x^2/((2n+1)(2n+2))<1, ie x^2<((2n+1)(2n+2))

On étudie donc le polynôme en n : P(n) = (2n+1)(2n+2)-x²=4n²+6n+2-x² (delta=4-16x²) et on sait qu’il sera positif quand n sera a l’extérieur de [n1,n2] ses deux racines si elles existent, et toujours positifs sinon
[remarque, le discriminant est non nul quand x appartient a B(0,1/2)]

Donc : si abs(x)<= 1/2 alors P(n)>=0 et (u_n) strict. décroissant
sinon, n>n2=(sqrt(4x²+1)-3)/4 => P(n)>=0 et a partir de ce rang : (u_n) strict. décroissant

j’espère pas m’être trompé :mrgreen:


Sinon pour le fameux calcul sur cos, j’avais juste voulu donner un exemple ou on pouvait calculer en serie entière et majorer le reste ^^

J’ai réfléchit à la question (éplucher mon formulaire sur le cos) et j’ai rien trouvé

Par contre le calcul en série entière ne me semble pas trop mauvais pour x compris entre -pi et pi, il commence à y avoir de l’attente quand x grandit, l’idée serait donc de faire un petit test préliminaire et à trouver z tel que x = z [2pi], z appartenant a B(0,pi)

Idée : utiliser la formule de la duplication et s’arreter quuand la valeur dans le cos est trop petite …

Mais intuitivement ca ne me parait pas performant

EDIT : code corrigé

Entrée : cos(a) Si a/2 > epsilon alors renvoyer 2*cos(a/2)**2-1 Sinon renvoyer 1-a**2/2 [et non pas 1 qui n'apportera rien de très concluant]

Faudrait réfléchir sur la majoration faite ici (choix du epsilon)

let rec cos_rec a eps = match a with
  | a when a/.2. > eps -> 2.*.(cos_rec( a /. 2. ))**2. -. 1. ;
  | a -> 1.-.a**2./.2.;;

cos_rec : float -> float -> float = <fun>

ici yavait une grosse erreur mais j’ai eu honte, donc je l’ai effacé ^^

:whistle:

[quote=“Tristan.T”]Idée : utiliser la formule de la duplication et s’arreter quuand la valeur dans le cos est trop petite …

Mais intuitivement ca ne me parait pas performant

Entrée : cos(a) Si a/2 > epsilon alors renvoyer 2*cos(a/2)**2-1 Sinon renvoyer 1

Faudrait réflechir sur la majoration faite ici (choix du epsilon)[/quote]

Si cos(a/2) vaut 1, alors 2*cos(a/2)-1 vaut 1, ce que tu obtiendras n’aura aucun chiffre significatif. Eventuellement utilise 1-a^2/2 mais il faut étudier la propagation des erreurs. Il y a d’autres méthodes géométriques où on fait tourner un vecteur fixe au démarrage d’angle teta0 connu et on écrit teta=somme(+/- teta0/2^k), on calcule le vecteur obtenu par multuiplication par les matrices de rotations qu’on peut calculer (on connait sin(teta0) et cos(teta0)), ça donne sin(teta) et cos(teta).

Ah oui mince :doh: , et en relisant mon code j’ai vu l’énorme erreur que j’avais commise (corrigé depuis) mais je me sens bien bête :mrgreen:

Du coup oui j’ai mis un DL à l’ordre 1. Ca marche (quelques chiffres significatif …)

[code]let a = 1. in
let t = ref (time()) in
let c = cos_rec (1.) 0.001 in
(time() -. !t),cos(1.)-.c;;

  • : float * float = 0.0, 1.33748309317e-07[/code]

Je m’en vais réfléchir à la méthode géométrique

Alors là désolé je ne vois pas [je viens de réviser la géométrie et tout le tralala en plus, j’ai attendu d’avoir revu ça pour pouvoir bien y réflechir]

teta=somme(+/- teta0/2^k)

On peut toujours écrire teta = somme(+/- teta0/2^k) :confused: :confused: :confused:

Par exemple si je prend teta0 = pi/2 et que je veux teta=1 … Il existe une décomposition : 1 = \sum_{k=0}^{infini ?, ou n ?} pi/2^{k+1} ? si oui comment on l’a trouve ?

Et quand bien même on l’aurait … je ne vois pas comment on pourait extraire le teta :108. Peut-être pourrais tu me conseiller un lien ^^

Voilà un jet rapide.
calculsincos.pdf (31.8 KB)

Nom d’un schtroumf, je me suis gourré dans mais calcul, il faut remplacer un -1 par 0 sinon les suites explosent. J’ai modifié le PDF ci dessus.

Reschtroumf, encore une coquille, c’est epsion(n)=1 si u(n)> teta0 et non u(0) > teta0!! Je remet la bonne version. En terme de précision c’est moyen si on veut une bonne précision: Ainsi avec des calculs à 420 décimales, je n’obtiens que 250 décimales exactes sur les valeurs des sinus et cosinus, il est vrai dans un délai très court. Les multiplicatons des matrices Bizarrement quand on retourne sur l’angle (arctan (sin/cos), on retrouve l’angle avec 340 à 350 décimales communes. Cela doit pouvoir permettre de corriger la valeur… Mais il est illusoire d’avoir plus des 4/5 des décimales exactes semble-t-il, il faudrait trouver une autre méthode, par exemple à l’aide de tangente, plus fiable. Je vais voir.
calculsincos.pdf (31.8 KB)