Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Problème d'arrondi en Java

5 réponses
Avatar
Christophe Rinaldi
Bonjour,

J'ai une classe tournant gr=E2ce a Junit qui me permet de tester un
ensemble de valeur d'arrondi.
On lui donne des valeurs en entr=E9e, on =E9crit les valeurs en sortie
que l'on attend, on lance JUnit et on esp=E8re que tous nos tests
fonctionnent. Mais l=E0 c'est pas le cas.

Je ne veut pas de l'arrondi standart de Java mais un autre style
d'arrondi.

J'ai bien une solution d=E9j=E0 mise en place mais elle n'est pas s=FBre
du tout et souvent je rencontre de nouveaux cas non g=E9r=E9.
Ainsi j'aimerait bien avoir un truc plus simple.

Sur mon jeu de test actuel en utilisant des m=E9thodes simples, j'ai
quand m=EAme trois erreurs.

Voici les erreurs :

Erreur sur 142.8685 , on attendait 142,869 et on a eu 142,868 !
Erreur sur 4.1234567885 , on attendait 4,123456789 et on a eu
4,123456788 !
Erreur sur -142.8685 , on attendait -142,869 et on a eu -142,868 !

Mes autres tests sont Ok.

Le pb viendrait du fait que l'arrondi 'normal' serait que lorsqu'on a
0=2E5 =E0 la fin d'un nombre on arrondisse au dessus alors que moi je
voudrais un arrondi au dessus.



Voici l'ensemble de ma classe qui suit.
Seule la fonction 'getFormattedValue' de fin du fichier est =E0
modifier.

Merci de votre aide.

Christophe.



import java.text.NumberFormat;
import java.util.Locale;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;


public class FormatTestVersionII extends TestCase
{

protected String labelWhenNull =3D "";

public FormatTestVersionII(String name)
{
super(name);
}

public static void main(String args[])
{
junit.textui.TestRunner.run(FormatTestVersionII.class);
}

public static Test suiteDisabled()
{
TestSuite suite =3D new TestSuite();
suite.addTest(new FormatTestVersionII("testVerifArrondi"));
return suite;
}

public void testVerifArrondi() throws Exception
{
double[] valeurDouble =3D { 4.55, 4.1542 , 4.1546, 4.0534,
4=2E0531, 4.0537, 142.8685, 4.1545 , 4.1535 , 4.0545, 4.0595,
4=2E0535};

String[] resultatAttendu =3D { "4,55", "4,154", "4,155",
"4,053","4,053","4,054","142,869", "4,155", "4,154" , "4,055" , "4,06"
, "4,054"};


for (int i =3D 0; i < valeurDouble.length; i++)
{
if ((getFormattedValue(valeurDouble[i], 3, 0, labelWhenNull,
NumberFormat

.getInstance(Locale.FRENCH)).equals(resultatAttendu[i])))
{
assertTrue(true);
}
else
{
System.out.println("Erreur sur "
+ valeurDouble[i]
+ " , on attendait "
+ resultatAttendu[i]
+ " et on a eu "
+ getFormattedValue(valeurDouble[i], 3, 0,
labelWhenNull, NumberFormat.getInstance(Locale.FRENCH))
+
" !");
assertTrue(false);
}

}
}


public void testVerifArrondi9Digit() throws Exception
{
double[] valeurDouble =3D { 4.1234567885 , 4.1234567895 };

String[] resultatAttendu =3D { "4,123456789", "4,12345679"};

for (int i =3D 0; i < valeurDouble.length; i++)
{
if ((getFormattedValue(valeurDouble[i], 9, 0, labelWhenNull,
NumberFormat

.getInstance(Locale.FRENCH)).equals(resultatAttendu[i])))
{
assertTrue(true);
}
else
{
System.out.println("Erreur sur "
+ valeurDouble[i]
+ " , on attendait "
+ resultatAttendu[i]
+ " et on a eu "
+ getFormattedValue(valeurDouble[i], 9, 0,
labelWhenNull, NumberFormat.getInstance(Locale.FRENCH))
+
" !");
assertTrue(false);
}

}
}


public void testVerifArrondiAvecDesMoins() throws Exception
{
double[] valeurDouble =3D { -4.55, -4.1542 , -4.1546,
-4.0534, -4.0531, -4.0537, -142.8685, -4.1545 , -4.1535 , -4.0545,
-4.0595, -4.0535, -53.555555, -38, -39938, -263997.177949};

String[] resultatAttendu =3D { "-4,55", "-4,154", "-4,155",
"-4,053","-4,053","-4,054","-142,869", "-4,155", "-4,154" , "-4,055" ,
"-4,06" , "-4,054", "-53,556", "-38", "-39938", "-263997,178"};


for (int i =3D 0; i < valeurDouble.length; i++)
{
if ((getFormattedValue(valeurDouble[i], 3, 0, labelWhenNull,
NumberFormat

.getInstance(Locale.FRENCH)).equals(resultatAttendu[i])))
{
assertTrue(true);
}
else
{
System.out.println("Erreur sur "
+ valeurDouble[i]
+ " , on attendait "
+ resultatAttendu[i]
+ " et on a eu "
+ getFormattedValue(valeurDouble[i], 3, 0,
labelWhenNull, NumberFormat.getInstance(Locale.FRENCH))
+
" !");
assertTrue(false);
}

}
}

public void testVerifArrondiSansChiffreApres() throws Exception
{
double[] valeurDouble =3D { -4.55, 4.1542 , -4.1546,
4=2E56534, -4.0531, -4.0537, -142.8685, -4.1545 , -4.1535 , -4.0545,
-4.0595, -4.0535, -53.555555, -38, -39938};

String[] resultatAttendu =3D { "-5", "4", "-4",
"5","-4","-4","-143", "-4", "-4" , "-4" , "-4" , "-4", "-54", "-38",
"-39938"};


for (int i =3D 0; i < valeurDouble.length; i++)
{
if ((getFormattedValue(valeurDouble[i], 0, 0, labelWhenNull,
NumberFormat

.getInstance(Locale.FRENCH)).equals(resultatAttendu[i])))
{
assertTrue(true);
}
else
{
System.out.println("Erreur sur "
+ valeurDouble[i]
+ " , on attendait "
+ resultatAttendu[i]
+ " et on a eu "
+ getFormattedValue(valeurDouble[i], 0, 0,
labelWhenNull, NumberFormat.getInstance(Locale.FRENCH))
+
" !");
assertTrue(false);
}

}
}

public void testVerifArrondiTestReel() throws Exception
{
double[] valeurDouble =3D { 12.159 };

String[] resultatAttendu =3D { "12,159"};


for (int i =3D 0; i < valeurDouble.length; i++)
{
if ((getFormattedValue(valeurDouble[i], 3, 0, labelWhenNull,
NumberFormat

.getInstance(Locale.FRENCH)).equals(resultatAttendu[i])))
{
assertTrue(true);
}
else
{
System.out.println("Erreur sur "
+ valeurDouble[i]
+ " , on attendait "
+ resultatAttendu[i]
+ " et on a eu "
+ getFormattedValue(valeurDouble[i], 3, 0,
labelWhenNull, NumberFormat.getInstance(Locale.FRENCH))
+
" !");
assertTrue(false);
}

}
}

public void testVerifArrondiTestEntier() throws Exception
{
double[] valeurDouble =3D { 35925203.0000, 35925203,
35438081.3840548 };

String[] resultatAttendu =3D { "35925203", "35925203" ,
"35438081"};


for (int i =3D 0; i < valeurDouble.length; i++)
{
if ((getFormattedValue(valeurDouble[i], 0, 0, labelWhenNull,
NumberFormat

.getInstance(Locale.FRENCH)).equals(resultatAttendu[i])))
{
assertTrue(true);
}
else
{
System.out.println("Erreur sur "
+ valeurDouble[i]
+ " , on attendait "
+ resultatAttendu[i]
+ " et on a eu "
+ getFormattedValue(valeurDouble[i], 0, 0,
labelWhenNull, NumberFormat.getInstance(Locale.FRENCH))
+
" !");
assertTrue(false);
}

}
}


/**
* @param d
* @param maxFractionDigit
* @param minFractionDigit
* @param defaultValueIfException
* @param nf
* @return Formatted Value
*/
public static String getFormattedValue(double d, int
maxFractionDigit, int minFractionDigit,
String defaultValueIfException, NumberFormat nf)
{
String value =3D defaultValueIfException;
try
{
// TODO : C'est ici qu'il faudrait trouver une solution
potable.

nf.setMaximumFractionDigits(maxFractionDigit);
nf.setMinimumFractionDigits(minFractionDigit);
nf.setGroupingUsed(false);

value =3D nf.format(d);
return value;
}
catch (Exception e)
{
return defaultValueIfException;
}
}


=20
}

5 réponses

Avatar
Christophe Tela
Christophe Rinaldi wrote:

J'ai une classe tournant grâce a Junit qui me permet de tester un
ensemble de valeur d'arrondi.
On lui donne des valeurs en entrée, on écrit les valeurs en sortie
que l'on attend, on lance JUnit et on espère que tous nos tests
fonctionnent. Mais là c'est pas le cas.

Je ne veut pas de l'arrondi standart de Java mais un autre style
d'arrondi.
As-tu regardé du côté de BigDecimal ? Cette classe permet de choisir parmi

de nombreuses méthodes d'arrondi...

Avatar
michaelm
La doc précise que pour DecimalFormat, le mode d'arrondi utilisé
lorsqu'on a 0.5 est ROUND_HALF_EVEN (nombre pair le plus proche), qui
n'est pas la méthode la plus habituelle, mais qui évite les effets de
cumul d'erreurs. NumberFormat semble utiliser la même méthode
d'arrondi, de même que la méthode Math.rint().

Pour choisir l'arrondi adapté à vos besoins, BigDecimal semble
effectivement être le seul recours.
Avatar
Christophe Rinaldi
Merci, je vais me re-regarder du coté de BigDecimal. J'avais déjà
essayer mais sans succès.

Si vous avez des pistes de recherches pour effectuer cet arrondi je
suis preneur !!
Avatar
Morphine
In article ,
"Christophe Rinaldi" wrote:

Merci, je vais me re-regarder du coté de BigDecimal. J'avais déjà
essayer mais sans succès.

Si vous avez des pistes de recherches pour effectuer cet arrondi je
suis preneur !!



Tu peux aussi faire un truc du genre :
double retour = (Math.round(x*Math.pow(10,arrondi)) )/
(Math.pow(10,arrondi));
Tu peux améliorer en vérifiant si Math.round retourne une valeur égale à
0.5 près, pour dans ce cas ajouter 1 avant de rediviser.

A+

Avatar
Vincent Cantin
Les nombres decimaux binaires ne sont generalement pas affichables de
maniere exacte avec peu de decimales. Les resultats que tu as recus, ainsi
que ceux que tu as entres, ont ete d'abord convertis en decimales binaires.
Je pense que c'est de la ou vient ton erreur entr ce que tu attends et ce
que tu obtiens. Je pense que si tu fesais le test directement en decimales
binaires, il se pourrait que tu n'ai pas d'erreurs.