juancho2786
Messages postés39Date d'inscriptionmardi 5 juillet 2005StatutMembreDernière intervention29 octobre 2008
-
19 nov. 2006 à 00:18
DonBanini
Messages postés1Date d'inscriptionlundi 16 février 2009StatutMembreDernière intervention 7 avril 2009
-
7 avril 2009 à 16:14
Bonsoir , je fais une méthode qui permet d'arrondir à n chiffres significatis seulement j'ai un problème. Par exemple lorsque le nombre à arrondir est 0.000023678 et j'aimerais l'arrondire à 3 chiffres significatifs, cela devrait donné 0.0000237 et pas 2370.0 comme c'est le cas dans ma méthode. Sinon pour le reste ça marche correctement, enfin je pense...
Avez vous une idée? merci beaucoup !!
voici la code :
public static double arrondiNChiffresSignificatifs(double nombre, int n){
char signe;
int exposant=0;
abdouinfomiage
Messages postés80Date d'inscriptionmardi 26 juillet 2005StatutMembreDernière intervention 3 février 2008 19 nov. 2006 à 03:41
public double round(double what, int howmuch) {
return (double)( (int)(what * Math.pow(10,howmuch) + .5) ) / Math.pow(10,howmuch);
}
System.out.println(round(1.6666666,2));
System.out.println(round(1.6666666,3));
System.out.println(round(1.6666666,0));Résultats :
}
regarde cet example et bonne chance
verdy_p
Messages postés202Date d'inscriptionvendredi 27 janvier 2006StatutMembreDernière intervention29 janvier 2019 9 avril 2008 à 03:17
abouinfoimage, ta solution est fausse et ne répond pas au problème. Il ne demande pas à arrondir un double sur N décimales, mais à N chiffres significatifs (à priori N < 17 car au delà, il n'y a plus aucun chiffre significatif et plus rien à arrondir dans un double) ; relis sa question, il a été très clair dans son exemple!
Son problème est moins simple qu'il y parait, car il faut faire attention à ne pas déborder en capacité pour des valeurs limites, ce qui peut arriver si on multiplie puis divise.
L’algo doit donc:
* trouver k, le logarithme de base 10 (arrondi à l'entier inférieur) du nombre x pour pouvoir le ramener à un intervalle entre 0,1 compris et 1,0 non compris (si on le divisait par 10^k); k est petit (à cause de la capacité maximale des "double", k sera entre -308 et 308 si je me souviens bien, pour les valeurs normales) et tient dans un entier;
* en ajoutant à cet entier le nombre de chiffre significatifs demandés N, on a un nombre dans l'intervalle entre 10^(N-1) compris et 10^N non compris afin de prendre l'entier arrondi; attention: pour N=16, 10^16 ne tient pas dans un "int", on doit utiliser Math.floor() (du moins tant que le nombre est positif.
* après l'arrondi, il reste à ramener à l'ordre de grandeur d'origine.
* on doit compléter en traitant spécialement l'arrondi de 0.0.
Ma solution est donc plutôt:
public static double arrondiNChiffresSignificatifs(final double x, final int n){
if (n < 1)
throw new BadArgumentException("n < 1");
if (n > 17)
return x;
if (x == 0)
return 0;
final double signedScale = x < 0 ?
-Math.pow(10, Math.floor(Math.log10(-x)) - n + 1) :
Math.pow(10, Math.floor(Math.log10(x)) - n + 1);
return Math.floor(x / signedScale + 0.5) * signedScale;
}
Note: l'arrondi est sans doute approximatif pour les valeurs dénormales très proches de 0, c'est à dire k <= -308, là où le logarithme de base 10 est aussi approximatif.
verdy_p
Messages postés202Date d'inscriptionvendredi 27 janvier 2006StatutMembreDernière intervention29 janvier 2019 9 avril 2008 à 03:28
pour l'arrondi à l'entier le plus proche j'ai utilisé Math.floor(x+0.5) dans l'instruction return; si tu veux l'arrondi IEEE à l'entier pair le plus proche quand on est juste au milieu de deux entiers, on peut aussi utiliser Math.round(x)... Cela ne change pas énormément les choses.
L'autre solution est d'utiliser la conversion via une chaine et un format, puis la conversion inverse, mais c'est bien plus lourd car Java gère le formatage en fonction d'une locale, et effectue des tas d'autres fonctions en interne pour gérer les formateurs de nombres, et réanalyser la chaîne.