Fonction inverse sinus (arcsin) et inverse cosinus (arccos) pour j2me

Soyez le premier à donner votre avis sur cette source.

Snippet vu 30 970 fois - Téléchargée 28 fois

Contenu du snippet

Cette function permet de calculer le sinus inverse d'un nombre. Cette fonction n'est pas a ma connaissance presente dans la librairie mathematique de J2ME (en tout cas je ne l'ai pas trouve), par contre elle est presente dans J2SE.
De la meme facon, connaissant le sinus inverse (arcsin), on peut determiner le cosinus inverse (arccos).

Le code n'est pas optimise et peut comporter quelques bugs (mais j'ai verifie sur plus de 10000 calculs).
La precision est de l'ordre de 10e-7 pour N=10.
L'etape suivante serait d'optimiser ce code...

La fonction pochhammer et factoriel sont aussi fournis dans ce code.

Source / Exemple :


import java.util.*;
import java.lang.*;

    /**

  • Function arcsin: return the inverse sinus in radian
  • You can also use it to calculate the arccos as arccos(z) = PI/2 - arcsin(z)
  • @param z the input param
  • @return the radian angle corresponding to the inverse sin of z.
  • /
private double arcsin(double z) { int k,i; int N = 30; // This number determines the precision, higher it is, higher the precision is. double res,tmp1,tmp2,tmp3; res = 0; if (Math.abs(z)<=0.5) { // = sum(k=0 a n) de (produit de j=0 a k-1 de (0.5+j))*z exp 2k+1) div (k! * 2k+1) for (k=0;k<N;k++) { tmp1 = prod(0.5,k); tmp2 = 1; for (i=0;i<2*k+1;i++) tmp2 *= z; tmp1 *= tmp2; tmp1 /= (2*k+1); tmp1 /= fact(k); res += tmp1; } } else if (z>0.5) { // = (Pi/2-Racine de 2*racine de 1-z)*Sum(k=0 a N) de (produit de j=0 a k-1 de (0.5+j))*(1-z) exp k) div (2exp k * k! * 2k+1) for (k=0;k<N;k++) { tmp1 = prod(0.5,k); tmp2 = 1; for (i=0;i<k;i++) tmp2 *= ((1-z)/2); tmp1 *= tmp2; tmp1 /= (2*k+1); tmp1 /= fact(k); res += tmp1; } res *= Math.sqrt(2)*Math.sqrt(1-z); res = Math.PI/2 - res; } else { // = (-Pi/2 + Racine de 2*racine de z+1)*Sum(k=0 a N) de (produit de j=0 a k-1 de (0.5+j))*(z+1) exp k) div (2exp k * k! * 2k+1) for (k=0;k<N;k++) { tmp1 = prod(0.5,k); tmp2 = 1; for (i=0;i<k;i++) tmp2 *= ((z+1)/2); tmp1 *= tmp2; tmp1 /= (2*k+1); tmp1 /= fact(k); res += tmp1; } res *= Math.sqrt(2)*Math.sqrt(z+1); res = res - Math.PI/2; } return res; } /** This function calculates the pochhammer
  • For n=0 return 1. For n=1 return a. For a=0 return 0. For a=1 return n!
  • @param a
  • @param n
  • @return n = product (from k=0 to n-1) of (a+k) [= (a)*(a+1)*...*(a+n-1)]
  • /
private double prod(double a,int n) { int k; double res=1; for (k=0;k<n;k++) res *= (a+k); return res; } /** This function calcultes the factorial
  • For n=0 return 1
  • @param n
  • @return n*(n-1)*...*2
  • /
private double fact(int n) { double res=1; for(int i=2;i<=n;i++) res *= i; return res; }

Conclusion :


Pour les explications theoriques sur ces differentes fonctions, je vous conseille d'aller faire un tour sur:
http://functions.wolfram.com/

A voir également

Ajouter un commentaire

Commentaires

Pole4
Messages postés
20
Date d'inscription
mardi 11 octobre 2005
Statut
Membre
Dernière intervention
13 mars 2007
-
Juste pour l'optimisation (si tu veux avoir quelques milliers de décimales) :
tmp1 /= fact(k);
tu peux mettre une variable que tu multiplie à chaque fois dans la boucle.
for (i=0;i<k;i++)
tmp2 *= ((z+1)/2);
même chose

Mais ces améliorations ne servent à rien si tu te sers que de 7 où 16 décimales.
Par contre, pour les BigDecimal, ça peut servir. (Il y a peut être une fonction arcsin dans la bibliothèque de BigDecimal, mais bon)
Pole4
Messages postés
20
Date d'inscription
mardi 11 octobre 2005
Statut
Membre
Dernière intervention
13 mars 2007
-
J'ai oublié pour la fonction de pochhammer :
on peut aussi s'en passer
une variable mis à 0.5 et à chaque boucle on multiplie par 0.5+k

Je verrais bien le début comme ça :
private double arcsin(double z) {
int k,i;
int N = 30; // This number determines the precision, higher it is, higher the precision is.
double res,tmp1,tmp2,tmp3,facto;

res = 0;
if (Math.abs(z)<=0.5) {
// = sum(k=0 a n) de (produit de j=0 a k-1 de (0.5+j))*z exp 2k+1) div (k! * k+1)
tmp2=z;tmp3=1;facto=1;
for (k=0;k<N;k++) {
tmp3 *= 0.5+k; // tmp3=prod(0.5,k)
tmp1 =tmp3*tmp2;
tmp1 /= (2*k+1);
tmp1 /= facto;
tmp2 *= z*z; // c'est le 2*k+1 de la boucle
if (k!=0) facto *=k; // facto=fact(k)
res += tmp1;
}
} else if (z>0.5) {

Voilà. Pour la suite change le "tmp2 *= z*z;" en "tmp2 *= z;".
(Je n'ai pas compilé le code, donc il peut y avoir des erreurs)
targ
Messages postés
1
Date d'inscription
samedi 13 septembre 2003
Statut
Membre
Dernière intervention
26 avril 2006
-
Un simple petit tour sur google t'aurais permis de constater qu'il existe déjà une fonction arcsin dans J2ME (Math.asin) qui est surement bien plus rapide que ta fonction.
cs_orelec
Messages postés
7
Date d'inscription
dimanche 4 juin 2006
Statut
Membre
Dernière intervention
15 octobre 2006
-
BidDecimal et BigInteger (classe java.math) ne contiennent aucune méthode de trigonométrie.
Pour la factorielle, un long est plus approprié qu'un double : dans un calcul avec deux types primitifs différents (un entier et un décimal) le résultat est du type de celui qui est décimal (on a soit un bug sur le type à la compillation, soit on utilise un cast).
Exemples :
float * int = float
double * int = long
On a également dans ces cas une erreur liée à l'approximation.
Dans le cas de la factorielle, on ne peut que dépasser les valeurs suivantes :
int : 12!
long : 20!
Au dessus pour une précision à l'unité, il faut utiliser la classe java.Math.BigInteger. En sachant également que le nombre de zéros est le suivant :
zéros = Math.floor(exposant / 5)
Formule qui permet de calculer la factorielle en utilisant les propriétés de calcul avec des puissances
cs_orelec
Messages postés
7
Date d'inscription
dimanche 4 juin 2006
Statut
Membre
Dernière intervention
15 octobre 2006
-
Grosse erreur de ma part :
double * int = double
Une ligne a été coupée involontairement :
double * long = long

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.