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/
12 oct. 2006 à 18:57
double * int = double
Une ligne a été coupée involontairement :
double * long = long
12 oct. 2006 à 18:54
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
26 avril 2006 à 09:19
24 oct. 2005 à 11:39
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)
24 oct. 2005 à 11:19
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)
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.