@swalest/decimal-processing
Version:
complete and advanced processing of decimal numbers
191 lines (174 loc) • 7.08 kB
text/typescript
import { Injectable } from "@nestjs/common";
import { Decimal } from 'decimal.js';
/*
* Service pour les opérations sur la finance ou les nombres décimaux
* @service FinancesService
*/
@Injectable()
export class FinancesService{
/**
* le traitement de l'adition de deux nombres décimaux
* @param {Decimal} a - le premier nombre
* @param {Decimal} b - le deuxième nombre
* @returns {Decimal} La somme de ces deux nombres
*/
add(a: Decimal, b: Decimal): Decimal {
return a.plus(b);
}
/**
* Le traitement de la soustraction de deux nombres décimaux
* @param {Decimal} a - le premier nombre
* @param {Decimal} b - le deuxième nombre
* @returns {Decimal} La soustration de ces deux nombres
*/
subtract(a: Decimal, b: Decimal): Decimal {
return a.minus(b);
}
/**
* Le traitement de la multiplication de deux nombres décimaux
* @param {Decimal} a - le premier nombre
* @param {Decimal} b - le deuxième nombre
* @returns {Decimal} Le produit de ces deux nombres
*/
multiply(a: Decimal, b: Decimal): Decimal {
return a.mul(b);
}
/**
* Division sécurisée avec gestion des erreurs et précision configurable
* @param {Decimal} dividend - le dividende
* @param {Decimal} divisor - le diviseur
* @param {number} decimalPlaces Nombre de décimales (par défaut: 2 pour les montants financiers)
* @throws {Decimal} le quotient de ce deux nombres ou Error si division par zéro
*/
divide(dividend: Decimal, divisor: Decimal, decimalPlaces: number = 2): Decimal {
if (divisor.equals(0)) {
throw new Error('Division par zéro non autorisée');
}
return dividend.dividedBy(divisor).toDecimalPlaces(decimalPlaces);
}
/**
*
* @param {Decimal} dividend - le dividende
* @param {Decimal} divisor - le diviseur
* @param {number} decimalPlaces - le nombre de chiffres après la virgule
* @returns {Decimal} - Le quotient de ces deux nombres ou l'erreur
*/
divideWithBankersRounding(
dividend: Decimal,
divisor: Decimal,
decimalPlaces: number = 2
): Decimal {
if (divisor.equals(0)) {
throw new Error('Division par zéro non autorisée');
}
return dividend.dividedBy(divisor)
.toDecimalPlaces(decimalPlaces, Decimal.ROUND_HALF_EVEN);
}
/**
* La comparaison pour déterminer la valeur la plus grande de ces deux nombres
* @param {Decimal} a - le premier nombre
* @param {Decimal} b - le deuxième nombre
* @returns {boolean} - la réponse
*/
isGreaterThan(a: Decimal, b: Decimal): boolean {
return a.greaterThan(b);
}
/**
* La comparaison pour déterminer la valeur la plus petite de ces deux nombres
* @param {Decimal} a - le premier nombre
* @param {Decimal} b - le deuxième nombre
* @returns {boolean} - la réponse
*/
isLessThan(a: Decimal, b: Decimal): boolean {
return a.lessThan(b);
}
/**
* La comparaison pour déterminer si les deux nombres donnés sont égaux
* @param {Decimal} a - le premier nombre
* @param {Decimal} b - le deuxième nombre
* @returns - la réponse
*/
isEqualThan(a: Decimal, b: Decimal): boolean {
return a.equals(b);
}
/**
* La comparaison si un nombre est supérieur ou égal à l'autre
* @param {Decimal} a - le premier nombre
* @param {Decimal} b - le deuxième nombre
* @returns - la réponse
*/
isGreaterOrEqualThan(a: Decimal, b: Decimal): boolean {
return a.greaterThanOrEqualTo(b);
}
/**
* La comparaison si un nombre est inférieur ou égal à un autre
* @param {Decimal} a - le premier nombre
* @param {Decimal} b - le deuxième nombre
* @returns - la réponse
*/
isLessOrEqualThan(a: Decimal, b: Decimal): boolean {
return a.lessThanOrEqualTo(b);
}
/**
* Le test si un nombre donné, est un nombre décimal
* @param {number} value - le nombre à tester
* @returns {boolean} - la réponse
*/
isDecimal(value: number): boolean {
try {
const d = new Decimal(value);
const entier: number = +(d.toString().split('.')[0]);
// Vérifie si le nombre a une partie décimale non nulle
return !d.equals(entier);
} catch (e) {
return false;
}
}
/**
* La conversion d'un nombre en décimal
* @param {number} value - le nombre à convertir
* @param {number} precision - le nombre de chiffres après la virgule
* @returns {Decimal} - le nombre décimal converti
*/
convertToDecimal(value: number, precision: number = 2): Decimal {
return new Decimal(value).toDecimalPlaces(precision);
}
/**
* L'arrondissement d'un nombre décimal
* @param {number | string} value - le nombre à arrondir
* @param {number} precision - le nombre de chiffres après la virgule
* @returns {Decimal} - le nombre décimal arrondi
*/
roundDecimal(value: number | string, precision: number = 2): Decimal {
return new Decimal(value).toDecimalPlaces(precision);
}
/**
* L'arrondissement avancé d'un nombre donné
* @param {number | Decimal} value - le nombre à arrondir
* @param {number} precision - le nombre de chiffres après la virgule
* @param {number} codeRounding - pour la détermination de rounding à appliquer
* @returns {Decimal} - le nombre arrondi
*/
advacedRoundDecimal(value: number | Decimal, precision: number = 2, codeRounding: number = 0): Decimal{
let rounding: any;
if(codeRounding === 0)
rounding = Decimal.ROUND_UP; // Vers +∞
else if(codeRounding === 1)
rounding = Decimal.ROUND_DOWN; // Vers -∞
else if(codeRounding === 2)
rounding = Decimal.ROUND_CEIL; // Vers +∞
else if(codeRounding === 3)
rounding = Decimal.ROUND_FLOOR; // Vers -∞
else if(codeRounding === 4)
rounding = Decimal.ROUND_HALF_UP; // Arrondi mathématique (0.5 vers le haut)
else if(codeRounding === 5)
rounding = Decimal.ROUND_HALF_DOWN; // 0.5 vers le bas
else if(codeRounding === 6)
rounding = Decimal.ROUND_HALF_EVEN; // Arrondi bancaire
else if(codeRounding === 7)
rounding = Decimal.ROUND_HALF_CEIL;
else if(codeRounding === 8)
rounding = Decimal.ROUND_HALF_FLOOR;
return new Decimal(value).toDecimalPlaces(precision, rounding);
}
}