Skip to content

Instantly share code, notes, and snippets.

@ghusta
Last active June 16, 2016 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ghusta/389559b51986521db0c3 to your computer and use it in GitHub Desktop.
Save ghusta/389559b51986521db0c3 to your computer and use it in GitHub Desktop.
Classe utilitaire pour la classe BigDecimal.
package fr.gouv.finances.douane.intercom.outils.lang;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.log4j.Logger;
/**
* Classe utilitaire pour la classe {@link BigDecimal}.
* <p>
* Permet par exemple d'eviter l'emploi du constructeur {@link BigDecimal#BigDecimal(double)} pouvant entrainer des erreurs.
* <br/>
* Cf. regle PMD <a href="http://pmd.sourceforge.net/pmd-4.3.0/rules/basic.html#AvoidDecimalLiteralsInBigDecimalConstructor">AvoidDecimalLiteralsInBigDecimalConstructor</a>
* </p>
*/
public final class BigDecimalUtils
{
private static final Logger LOGGER = Logger.getLogger(BigDecimalUtils.class);
/**
* BigDecimal : ZERO.
*
* @deprecated Utiliser {@link BigDecimal#ZERO}
*/
@Deprecated
public static final BigDecimal BIG_DEC_ZERO = BigDecimal.ZERO;
/**
* BigDecimal : UN.
*
* @deprecated Utiliser {@link BigDecimal#ONE}
*/
@Deprecated
public static final BigDecimal BIG_DEC_UN = BigDecimal.ONE;
/**
* BigDecimal : DIX.
*
* @deprecated Utiliser {@link BigDecimal#TEN}
*/
@Deprecated
public static final BigDecimal BIG_DEC_DIX = BigDecimal.TEN;
/**
* BigDecimal : CENT.
*/
public static final BigDecimal BIG_DEC_CENT = BigDecimal.valueOf(100);
/**
* BigDecimal : MILLE.
*/
public static final BigDecimal BIG_DEC_MILLE = BigDecimal.valueOf(1000);
public static final MathContext MATH_CONTEXT_ARRONDI_MONETAIRE_EURO = new MathContext(2, RoundingMode.HALF_UP);
/**
* Constructeur prive.
*/
private BigDecimalUtils()
{
}
/**
* Creer un BigDecimal a partir d'un int sans passer par le constructeur {@link BigDecimal#BigDecimal(double)}.
* <br>
* Regle PMD explicative : <a href="http://pmd.sourceforge.net/pmd-4.3.0/rules/basic.html#AvoidDecimalLiteralsInBigDecimalConstructor">AvoidDecimalLiteralsInBigDecimalConstructor</a>
*
* @param nb
* @return
* @since 1.4
*/
public static BigDecimal createBigDecimal(int nb)
{
return BigDecimal.valueOf(nb);
}
/**
* Creer un BigDecimal a partir d'un long sans passer par le constructeur {@link BigDecimal#BigDecimal(double)}.
* <br>
* Regle PMD explicative : <a href="http://pmd.sourceforge.net/pmd-4.3.0/rules/basic.html#AvoidDecimalLiteralsInBigDecimalConstructor">AvoidDecimalLiteralsInBigDecimalConstructor</a>
*
* @param nb
* @return
* @since 1.4
*/
public static BigDecimal createBigDecimal(long nb)
{
return BigDecimal.valueOf(nb);
}
/**
* Creer un BigDecimal a partir d'un double sans passer par le constructeur {@link BigDecimal#BigDecimal(double)}.
* <br>
* Regle PMD explicative : <a href="http://pmd.sourceforge.net/pmd-4.3.0/rules/basic.html#AvoidDecimalLiteralsInBigDecimalConstructor">AvoidDecimalLiteralsInBigDecimalConstructor</a>
*
* @param nb
* @return
* @since 1.4
*/
public static BigDecimal createBigDecimal(double nb)
{
// Methode utilisee dans JDK 1.5 dans la methode :
// public static BigDecimal valueOf(double val)
return new BigDecimal(Double.toString(nb));
}
/**
* Creer un BigDecimal a partir d'un double sans passer par le constructeur {@link BigDecimal#BigDecimal(double)}.
* <br>
* Regle PMD explicative : <a href="http://pmd.sourceforge.net/pmd-4.3.0/rules/basic.html#AvoidDecimalLiteralsInBigDecimalConstructor">AvoidDecimalLiteralsInBigDecimalConstructor</a>
*
* @param nb
* @param newScale
* @param roundingMode
* @return
* @since 1.5
*/
public static BigDecimal createBigDecimalWithScale(double nb, int newScale, RoundingMode roundingMode)
{
BigDecimal roundedBg = new BigDecimal(Double.toString(nb));
roundedBg = roundedBg.setScale(newScale, roundingMode);
return roundedBg;
}
/**
* Creer un BigDecimal a partir d'un float sans passer par le constructeur {@link BigDecimal#BigDecimal(double)}.
* <br>
* Regle PMD explicative : <a href="http://pmd.sourceforge.net/pmd-4.3.0/rules/basic.html#AvoidDecimalLiteralsInBigDecimalConstructor">AvoidDecimalLiteralsInBigDecimalConstructor</a>
*
* @param nb
* @return
* @since 1.4
*/
public static BigDecimal createBigDecimal(float nb)
{
return new BigDecimal(Float.toString(nb));
}
/**
* Creer un BigDecimal a partir d'un String.
*
* @param str
* @return
* @see NumberUtils#createBigDecimal(String)
*/
public static BigDecimal createBigDecimal(String str)
{
return NumberUtils.createBigDecimal(str);
}
/**
* <p>Retourne soit le BigDecimal passe en parametre,
* ou s'il est {@code null}, retourne {@code BigDecimal.ZERO}.</p>
* <p/>
* <pre>
* BigDecimalUtils.defaultBigDecimal(null) == BigDecimal.ZERO
* BigDecimal bigDecimal1 <- new BigDecimal("12.34")
* BigDecimalUtils.defaultBigDecimal(bigDecimal1) == bigDecimal1
* </pre>
*
* @param bigDec Peut etre null
* @return le BigDecimal passe en parametre, ou {@code BigDecimal.ZERO}
* s'il est {@code null}
* @see StringUtils#defaultString(String)
*/
public static BigDecimal defaultBigDecimal(BigDecimal bigDec)
{
return bigDec == null ? BigDecimal.ZERO : bigDec;
}
/**
* Addition d'une liste variable de {@link BigDecimal}.
* <br/>
* Methode null-safe : si un nombre est {@code null}, on prend par defaut zero.
*
* @param firstNumber
* @param numbers
* @return Resultat de l'addition.
* @see BigDecimal#add(BigDecimal)
*/
public static BigDecimal add(BigDecimal firstNumber, BigDecimal... numbers)
{
BigDecimal result = defaultBigDecimal(firstNumber);
for (BigDecimal nb : numbers)
{
result = result.add(defaultBigDecimal(nb));
}
return result;
}
public static BigDecimal add(Iterable<BigDecimal> numbers)
{
BigDecimal result = BigDecimal.ZERO;
for (BigDecimal nb : numbers)
{
result = result.add(defaultBigDecimal(nb));
}
return result;
}
/**
* Soustraction d'une liste variable de {@link BigDecimal}.
* <br/>
* Methode null-safe : si un nombre est {@code null}, on prend par defaut zero.
*
* @param firstNumber
* @param numbers
* @return Resultat de la soustraction.
* @see BigDecimal#subtract(BigDecimal)
*/
public static BigDecimal subtract(BigDecimal firstNumber, BigDecimal... numbers)
{
BigDecimal result = defaultBigDecimal(firstNumber);
for (BigDecimal nb : numbers)
{
result = result.subtract(defaultBigDecimal(nb));
}
return result;
}
/**
* Multiplication d'une liste variable de {@link BigDecimal}.
* <br/>
* Methode null-safe : si un nombre est {@code null}, on prend par defaut zero.
*
* @param firstNumber
* @param numbers
* @return Resultat de la multiplication.
* @see BigDecimal#multiply(BigDecimal)
*/
public static BigDecimal multiply(BigDecimal firstNumber, BigDecimal... numbers)
{
BigDecimal result = defaultBigDecimal(firstNumber);
for (BigDecimal nb : numbers)
{
result = result.multiply(defaultBigDecimal(nb));
}
return result;
}
/**
* Division d'une liste variable de {@link BigDecimal}.
* <br/>
* Methode null-safe : si un nombre est {@code null}, on prend par defaut zero.
*
* @param firstNumber
* @param numbers
* @return Resultat de la division.
* @throws ArithmeticException Si erreur
* @see BigDecimal#divide(BigDecimal)
* @deprecated Utiliser de preference {@link #divide(RoundingMode, BigDecimal, BigDecimal...)}.
*/
@Deprecated
public static BigDecimal divide(BigDecimal firstNumber, BigDecimal... numbers)
{
BigDecimal result = defaultBigDecimal(firstNumber);
for (BigDecimal nb : numbers)
{
result = result.divide(defaultBigDecimal(nb));
}
return result;
}
/**
* Division d'une liste variable de {@link BigDecimal}, avec regle d'arrondi.
* <br/>
* Methode null-safe : si un nombre est {@code null}, on prend par defaut zero.
*
* @param roundingMode Regle d'arrondi
* @param firstNumber
* @param numbers
* @return Resultat de la division.
* @throws ArithmeticException Si erreur
* @see BigDecimal#divide(BigDecimal, RoundingMode)
*/
public static BigDecimal divide(RoundingMode roundingMode, BigDecimal firstNumber, BigDecimal... numbers)
{
BigDecimal result = defaultBigDecimal(firstNumber);
for (BigDecimal nb : numbers)
{
result = result.divide(defaultBigDecimal(nb), roundingMode);
}
return result;
}
/**
* Division d'une liste variable de {@link BigDecimal}, avec definition du nombre de decimales
* et regle d'arrondi.
* <br/>
* Methode null-safe : si un nombre est {@code null}, on prend par defaut zero.
*
* @param scale Nombre de decimales
* @param roundingMode Regle d'arrondi
* @param firstNumber
* @param numbers
* @return Resultat de la division.
* @throws ArithmeticException Si erreur
* @see BigDecimal#divide(BigDecimal, RoundingMode)
*/
public static BigDecimal divide(int scale, RoundingMode roundingMode, BigDecimal firstNumber, BigDecimal... numbers)
{
BigDecimal result = defaultBigDecimal(firstNumber);
for (BigDecimal nb : numbers)
{
result = result.divide(defaultBigDecimal(nb), scale, roundingMode);
}
return result;
}
/**
* Division d'une liste variable de {@link BigDecimal}, avec definition du nombre de decimales
* et regle d'arrondi.
* <br/>
* Methode null-safe : si un nombre est {@code null}, on prend par defaut zero.
*
* @param mc
* @param firstNumber
* @param numbers
* @return Resultat de la division.
* @throws ArithmeticException Si erreur
* @see BigDecimal#divide(BigDecimal, MathContext)
*/
public static BigDecimal divide(MathContext mc, BigDecimal firstNumber, BigDecimal... numbers)
{
BigDecimal result = defaultBigDecimal(firstNumber);
for (BigDecimal nb : numbers)
{
result = result.divide(defaultBigDecimal(nb), mc);
}
return result;
}
/**
* Retourne le max d'une liste de BigDecimal.
*
* @param firstNumber
* @param numbers
* @return Valeur max.
* @see BigDecimal#max(BigDecimal)
*/
public static BigDecimal max(BigDecimal firstNumber, BigDecimal... numbers)
{
if (firstNumber == null)
{
throw new IllegalArgumentException("1er parametre null");
}
BigDecimal result = firstNumber;
for (BigDecimal nb : numbers)
{
result = result.max(nb);
}
return result;
}
/**
* Retourne le max d'une liste de BigDecimal.
*
* @param numbers
* @return Valeur max.
* @see BigDecimal#max(BigDecimal)
*/
public static BigDecimal max(Iterable<BigDecimal> numbers)
{
BigDecimal result = null;
for (BigDecimal nb : numbers)
{
if (result == null)
{
// 1ere iteration
result = nb;
}
else
{
result = result.max(nb);
}
}
return result;
}
/**
* Retourne le min d'une liste de BigDecimal.
*
* @param firstNumber
* @param numbers
* @return Valeur min.
* @see BigDecimal#min(BigDecimal)
*/
public static BigDecimal min(BigDecimal firstNumber, BigDecimal... numbers)
{
if (firstNumber == null)
{
throw new IllegalArgumentException("1er parametre null");
}
BigDecimal result = firstNumber;
for (BigDecimal nb : numbers)
{
result = result.min(nb);
}
return result;
}
/**
* Retourne le min d'une liste de BigDecimal.
*
* @param numbers
* @return Valeur min.
* @see BigDecimal#min(BigDecimal)
*/
public static BigDecimal min(Iterable<BigDecimal> numbers)
{
BigDecimal result = null;
for (BigDecimal nb : numbers)
{
if (result == null)
{
// 1ere iteration
result = nb;
}
else
{
result = result.min(nb);
}
}
return result;
}
/**
* Comparer deux instances de {@link BigDecimal}.<br/>
* La plupart du temps, il est preferable d'utiliser
* la methode <code>compareTo()</code> plutot que <code>equals()</code> dans le cas de la classe BigDecimal.
*
* @param bd1
* @param bd2
* @return Nombre entier, 0 si egaux.
* @see BigDecimal#compareTo(BigDecimal)
*/
public static int compare(BigDecimal bd1, BigDecimal bd2)
{
return bd1.compareTo(bd2);
}
/**
* Raccourci pour la methode {@link #compare(BigDecimal, BigDecimal)}.
*
* @param bd1
* @param bd2
* @return true si comparables.
* @see BigDecimalUtils#compare(BigDecimal, BigDecimal)
*/
public static boolean isComparable(BigDecimal bd1, BigDecimal bd2)
{
return compare(bd1, bd2) == 0;
}
/**
* Raccourci pour la methode {@link #compare(BigDecimal, BigDecimal)}.
*
* @param bd1
* @param bd2
* @return true si non comparables.
* @see BigDecimalUtils#compare(BigDecimal, BigDecimal)
*/
public static boolean isNotComparable(BigDecimal bd1, BigDecimal bd2)
{
return compare(bd1, bd2) != 0;
}
/**
* Raccourci pour la methode {@link BigDecimal#compareTo(BigDecimal)} différent de ZERO.
*
* @param bd1
* @return true si non comparable a ZERO.
*/
public static boolean isNotComparableToZero(BigDecimal bd1)
{
return bd1.compareTo(BigDecimal.ZERO) != 0;
}
/**
* Raccourci pour la methode {@link BigDecimal#compareTo(BigDecimal)} avec ZERO.
*
* @param bd1
* @return true si comparable a ZERO.
*/
public static boolean isComparableToZero(BigDecimal bd1)
{
return bd1.compareTo(BigDecimal.ZERO) == 0;
}
/**
* Raccourci pour la methode {@link BigDecimal#compareTo(BigDecimal)} avec ZERO.
*
* @param bd1
* @return resultat entier de la comparaison avec ZERO (-1, 0 ou 1).
* @see BigDecimal#compareTo(BigDecimal)
*/
public static int compareToZero(BigDecimal bd1)
{
return bd1.compareTo(BigDecimal.ZERO);
}
/**
* Détermine si un BigDecimal est strictement positif.
*
* @param bd1 Nombre
* @return
* @see BigDecimal#signum()
*/
public static boolean isPositive(BigDecimal bd1)
{
return bd1.signum() == 1;
}
/**
* Détermine si un BigDecimal est positif ou nul.
*
* @param bd1 Nombre
* @return
* @see BigDecimal#signum()
*/
public static boolean isPositiveOrZero(BigDecimal bd1)
{
return bd1.signum() >= 0;
}
/**
* Détermine si un BigDecimal est strictement négatif.
*
* @param bd1 Nombre
* @return
* @see BigDecimal#signum()
*/
public static boolean isNegative(BigDecimal bd1)
{
return bd1.signum() == -1;
}
/**
* Détermine si un BigDecimal est négatif ou nul.
*
* @param bd1 Nombre
* @return
* @see BigDecimal#signum()
*/
public static boolean isNegativeOrZero(BigDecimal bd1)
{
return bd1.signum() <= 0;
}
/**
* Détermine si un BigDecimal est égal à 0 (conformément à {@link BigDecimal#signum()}).
*
* @param bd1 Nombre
* @return
* @see BigDecimal#signum()
*/
public static boolean isZero(BigDecimal bd1)
{
return bd1.signum() == 0;
}
/**
* Appel de {@link BigDecimal#setScale(int)}
* <br/>
* Methode null-safe.
*
* @param bd BigDecimal en entree
* @param newScale scale en entree
* @return Nouveau BigDecimal, ou {@code null} si BigDecimal null en entree
* @throws ArithmeticException if the specified scaling operation would require rounding.
* @see BigDecimal#setScale(int)
* @deprecated Utiliser de preference {@link #changeScale(BigDecimal, int, RoundingMode)}.
*/
@Deprecated
public static BigDecimal changeScale(final BigDecimal bd, int newScale)
{
if (bd == null)
{
return null;
}
return bd.setScale(newScale);
}
/**
* Appel de {@link BigDecimal#setScale(int, RoundingMode)} (avec regle d'arrondi).
* <br/>
* Methode null-safe.
*
* @param bd BigDecimal en entree
* @param newScale scale en entree
* @param roundingMode Regle d'arrondi
* @return Nouveau BigDecimal, ou {@code null} si BigDecimal null en entree
* @throws ArithmeticException if roundingMode==UNNECESSARY and the specified scaling operation would require rounding.
* @see BigDecimal#setScale(int)
*/
public static BigDecimal changeScale(final BigDecimal bd, int newScale, RoundingMode roundingMode)
{
if (bd == null)
{
return null;
}
return bd.setScale(newScale, roundingMode);
}
/**
* Appel de {@link BigDecimal#setScale(int, RoundingMode)} (avec regle d'arrondi).
*
* @param bd
* @param mathContext
* @return Nouveau BigDecimal, ou {@code null} si BigDecimal null en entree
* @throws ArithmeticException if roundingMode==UNNECESSARY and the specified scaling operation would require rounding.
*/
public static BigDecimal changeScale(final BigDecimal bd, final MathContext mathContext)
{
if (bd == null)
{
return null;
}
return bd.setScale(mathContext.getPrecision(), mathContext.getRoundingMode());
}
/**
* Converts this {@code BigDecimal} to a {@code BigInteger},
* checking for lost information. An exception is thrown if this
* {@code BigDecimal} has a nonzero fractional part.
*
* @param bd
* @return {@code BigDecimal} converted to a {@code BigInteger}, or {@code null}.
* @throws ArithmeticException if {@code this} has a nonzero fractional part.
* @see BigDecimal#toBigIntegerExact()
*/
public static BigInteger toBigIntegerExact(final BigDecimal bd)
{
if (bd == null)
{
return null;
}
return bd.toBigIntegerExact();
}
/**
* Tronquer la partie decimale de {@code BigDecimal} non nécessaire.
*
* @param bd {@code BigDecimal} en entrée.
* @return Nouveau {@code BigDecimal}, ou {@code null}.
* @throws ArithmeticException Pb arrondi
* @see BigDecimal#toBigIntegerExact()
* @see BigDecimal#stripTrailingZeros()
*/
public static BigDecimal toBigDecimalWithoutFractionalPart(final BigDecimal bd)
{
if (bd == null)
{
return null;
}
return bd.setScale(0, BigDecimal.ROUND_UNNECESSARY);
}
/**
* Obtenir la partie décimale d'un {@code BigDecimal} uniquement.
* <pre>
* getFractionalPart(new BigDecimal( "-12.5689" )) => new BigInteger("5689")
* </pre>
*
* @param bd Nombre en entrée.
* @return BigInteger
*/
public static BigInteger getFractionalPart(final BigDecimal bd)
{
if (bd == null)
{
return null;
}
// soit le reste de la division entiere par 1 (val absolue)
BigDecimal remainder = bd.remainder(BigDecimal.ONE).abs();
return new BigInteger(remainder.toString().substring("0.".length()));
}
/**
* Applique la regle d'arrondi par defaut pour les montants monetaires.
* <br>
* Soit 2 decimales, et arrondi {@link RoundingMode#HALF_UP}.
*
* @param bd Montant en entree.
* @return Nouveau Montant
*/
public static BigDecimal arrondiMonetaire(final BigDecimal bd)
{
return changeScale(bd, MATH_CONTEXT_ARRONDI_MONETAIRE_EURO.getPrecision(),
MATH_CONTEXT_ARRONDI_MONETAIRE_EURO.getRoundingMode());
}
/**
* Calcul de repartition d'une somme au <b>prorata</b>.
* <br>
* <a href="http://stackoverflow.com/questions/1925691/proportionately-distribute-prorate-a-value-across-a-set-of-values">lien stackoverflow</a>
*
* @param montantRepartir Montant a repartir.
* @param montantsReference Liste des montants. Chacun represente un poids.
* @return Liste ordonnée de montants.
*/
public static List<BigDecimal> calculerProrata(final BigDecimal montantRepartir, final List<BigDecimal> montantsReference)
{
return calculerProrata(montantRepartir, montantsReference, null);
}
/**
* Calcul de repartition d'une somme au <b>prorata</b>.
*
* @param montantRepartir Montant a repartir.
* @param montantsReference Liste des montants. Chacun represente un poids.
* @param mcArrondi Regle d'arrondi a appliquer
* @return Liste ordonnée de montants.
*/
public static List<BigDecimal> calculerProrata(final BigDecimal montantRepartir, final List<BigDecimal> montantsReference,
final MathContext mcArrondi)
{
MathContext mc = new MathContext(10, RoundingMode.HALF_UP);
// à  priori pas besoin de ce ctrl ?
boolean interdireDepassementMontantRepartir = false;
if (montantRepartir == null || BigDecimalUtils.isNegative(montantRepartir))
{
throw new IllegalArgumentException("Parametre 'montantRepartir' invalide (" + montantRepartir + ")");
}
if (montantRepartir.compareTo(BigDecimal.ZERO) == 0)
{
// retourner liste init à 0
List<BigDecimal> listeZeros = new ArrayList<BigDecimal>(montantsReference.size());
for (int i = 0; i < montantsReference.size(); i++)
{
listeZeros.add(BigDecimal.ZERO);
}
return listeZeros;
}
if (montantsReference == null || montantsReference.isEmpty())
{
throw new IllegalArgumentException("Parametre 'montantsReference' invalide");
}
List<BigDecimal> resultats = new ArrayList<BigDecimal>();
BigDecimal sommeMontantsImpactes = BigDecimalUtils.add(montantsReference);
// regle a definir si besoin ?
if (interdireDepassementMontantRepartir)
{
if (montantRepartir.compareTo(sommeMontantsImpactes) > 0)
{
throw new IllegalArgumentException("Le montant a repartir ne peut etre superieur a la somme des montants");
}
}
// verifier que la regle d'arrondi s'applique au montant a repartir
BigDecimal montantRepartirArrondi = null;
if (mcArrondi != null)
{
montantRepartirArrondi = montantRepartir.setScale(mcArrondi.getPrecision(), mcArrondi.getRoundingMode());
// FIXME: a confirmer, mais on n'utilise pas le montant a repartir arrondi par la suite...
// d'ou la possibilité d'une difference et une ArithmeticException
}
// calcul : montant prorata = poids / somme poids * montant repartir
BigDecimal resteRepartir = montantRepartir;
int maxMontantRefIndex = -1;
for (int i = 0; i < montantsReference.size(); i++)
{
BigDecimal montantRef = montantsReference.get(i);
BigDecimal quotePart;
// trouver l'indice max, en cas de resteRepartir > 0
if (i == 0)
{
maxMontantRefIndex = 0;
}
else
{
if (montantRef.compareTo(montantsReference.get(i - 1)) > 0)
{
maxMontantRefIndex = i;
}
}
// multiply avant divide
BigDecimal m = montantRef.multiply(montantRepartir);
quotePart = m.divide(sommeMontantsImpactes, mc);
if (mcArrondi != null)
{
// appliquer arrondi
quotePart = quotePart.setScale(mcArrondi.getPrecision(), mcArrondi.getRoundingMode());
}
// calcul reste
resteRepartir = resteRepartir.subtract(quotePart);
resultats.add(quotePart);
}
// si resteRepartir != 0 ?
if (resteRepartir.compareTo(BigDecimal.ZERO) != 0)
{
BigDecimal nouveauMt = null;
if (mcArrondi != null)
{
nouveauMt =
resultats.get(maxMontantRefIndex).add(
resteRepartir.setScale(mcArrondi.getPrecision(), mcArrondi.getRoundingMode()));
}
else
{
nouveauMt = resultats.get(maxMontantRefIndex).add(resteRepartir);
}
resultats.set(maxMontantRefIndex, nouveauMt);
}
// Verification si repartition avec perte
BigDecimal sommeMontantsApresRepartition = BigDecimalUtils.add(resultats);
if (montantRepartir.compareTo(sommeMontantsApresRepartition) != 0)
{
BigDecimal diffArrondiMontantRepartir = BigDecimal.ZERO;
if (mcArrondi != null)
{
diffArrondiMontantRepartir = montantRepartir.subtract(montantRepartirArrondi);
}
LOGGER.debug("calculerProrata : diffArrondiMontantRepartir = " + diffArrondiMontantRepartir);
BigDecimal diff = montantRepartir.subtract(sommeMontantsApresRepartition);
throw new ArithmeticException(
"La repartition ne tombe pas juste ! (diff = " + diff + "). Données calcul : montantRepartir = ["
+ montantRepartir + "]; montantsReference = [" + StringUtils.join(montantsReference, ", ") + "]");
}
return resultats;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment