1. Introduction
La bibliothèque Go Decimal est un outil puissant pour manipuler des décimales à virgule fixe de précision arbitraire dans le langage Go. Il permet d'effectuer des opérations d'addition, de soustraction, de multiplication et de division sans perdre de précision. De plus, il fournit des fonctionnalités telles que la sérialisation/désérialisation de base de données/SQL, ainsi que la sérialisation/désérialisation JSON/XML.
2. Installation
Pour installer la bibliothèque Go Decimal, vous pouvez utiliser la commande suivante :
go get github.com/shopspring/decimal
Veuillez noter que la bibliothèque Decimal nécessite la version Go >=1.7.
3. Utilisation de base
Pour utiliser la bibliothèque Decimal dans un programme Go, importez le package "github.com/shopspring/decimal". Voici un code d'exemple simple démontrant l'utilisation de base :
package main
import (
"fmt"
"github.com/shopspring/decimal"
)
func main() {
price, err := decimal.NewFromString("136.02")
if err != nil {
panic(err)
}
quantity := decimal.NewFromInt(3)
fee, _ := decimal.NewFromString(".035")
taxRate, _ := decimal.NewFromString(".08875")
subtotal := price.Mul(quantity)
preTax := subtotal.Mul(fee).Add(decimal.NewFromFloat(1))
total := preTax.Mul(taxRate).Add(decimal.NewFromFloat(1))
fmt.Println("Sous-total:", subtotal) // Sous-total: 408.06
fmt.Println("Avant impôt:", preTax) // Avant impôt: 422.3421
fmt.Println("Impôts:", total.Sub(preTax)) // Impôts: 37.482861375
fmt.Println("Total:", total) // Total: 459.824961375
fmt.Println("Taux d'imposition:", total.Sub(preTax).Div(preTax)) // Taux d'imposition: 0.08875
}
4. Création de variables Decimal
La bibliothèque Decimal fournit différentes méthodes pour créer des variables Decimal. Voici les API prises en charge :
-
decimal.NewFromBigInt(value *big.Int, exp int32) Decimal
-
decimal.NewFromFloat(value float64) Decimal
-
decimal.NewFromFloat32(value float32) Decimal
-
decimal.NewFromFloatWithExponent(value float64, exp int32) Decimal
-
decimal.NewFromFormattedString(value string, replRegexp *regexp.Regexp) (Decimal, error)
-
decimal.NewFromInt(value int64) Decimal
-
decimal.NewFromInt32(value int32) Decimal
-
decimal.NewFromString(value string) (Decimal, error)
-
decimal.RequireFromString(value string) Decimal
5. Opérations arithmétiques
La bibliothèque Go Decimal propose plusieurs opérations arithmétiques qui peuvent être effectuées sur des variables Decimal. Voici quelques opérations prises en charge :
-
Add(d2 Decimal) Decimal
: Ajoute deux valeurs Decimal et renvoie le résultat. -
Sub(d2 Decimal) Decimal
: Soustrait une valeur Decimal d'une autre et renvoie le résultat. -
Div(d2 Decimal) Decimal
: Divise une valeur Decimal par une autre et renvoie le résultat. -
DivRound(d2 Decimal, précision int32) Decimal
: Divise une valeur Decimal par une autre et renvoie le résultat avec la précision spécifiée. -
Mod(d2 Decimal) Decimal
: Calcule le modulo (reste) d'une valeur Decimal divisée par une autre et renvoie le résultat. -
Mul(d2 Decimal) Decimal
: Multiplie deux valeurs Decimal et renvoie le résultat.
Vous pouvez utiliser ces opérations pour effectuer des calculs arithmétiques courants sur les valeurs Decimal. Voici un exemple illustrant l'utilisation de ces opérations :
price, _ := decimal.NewFromString("136.02")
quantity := decimal.NewFromInt(3)
subtotal := price.Mul(quantity)
tax := subtotal.Mul(decimal.NewFromFloat(0.08875))
total := subtotal.Add(tax)
fmt.Println("Sous-total:", subtotal) // Sous-total: 408.06
fmt.Println("Impôt:", tax) // Impôt: 36.244985
fmt.Println("Total:", total) // Total: 444.304985
Dans l'exemple ci-dessus, nous utilisons la méthode Mul()
pour calculer le sous-total
en multipliant price
et quantity
. Ensuite, nous calculons tax
en multipliant subtotal
par le taux d'imposition. Enfin, nous calculons total
en ajoutant subtotal
et tax
à l'aide de la méthode Add()
.
6. Opérations d'arrondi
La bibliothèque Go Decimal propose plusieurs opérations d'arrondi qui peuvent être utilisées pour arrondir des valeurs décimales à une précision spécifiée. Voici quelques opérations d'arrondi disponibles :
-
Round(places int32) Decimal
: Arrondit le décimal au nombre spécifié de décimales. -
RoundBank(places int32) Decimal
: Arrondit le décimal en utilisant l'arrondi bancaire au nombre spécifié de décimales. -
RoundCash(interval uint8) Decimal
: Arrondit le décimal à un intervalle spécifique, tel que 5 cents, 10 cents, 25 cents, 50 cents ou 1 dollar. -
RoundCeil(places int32) Decimal
: Arrondit le décimal vers l'infini positif. -
RoundDown(places int32) Decimal
: Arrondit le décimal vers zéro. -
RoundFloor(places int32) Decimal
: Arrondit le décimal vers l'infini négatif. -
RoundUp(places int32) Decimal
: Arrondit le décimal à l'opposé de zéro.
6.1. Arrondi
Arrondi arrondit le décimal au nombre spécifié de décimales. Si places < 0, il arrondit la partie entière au nombre le plus proche de 10^(-places).
NewFromFloat(5.45).Round(1).String() // Résultat : "5.5"
NewFromFloat(545).Round(-1).String() // Résultat : "550"
6.2. Arrondi Bancaire
Arrondi Bancaire arrondit le décimal à places décimales. Si la distance entre le dernier chiffre à arrondir et les deux entiers les plus proches est égale, la valeur arrondie prend le nombre pair.
Si places < 0, la partie entière sera arrondie au nombre le plus proche de 10^(-places).
NewFromFloat(5.45).RoundBank(1).String() // Résultat : "5.4"
NewFromFloat(545).RoundBank(-1).String() // Résultat : "540"
NewFromFloat(5.46).RoundBank(1).String() // Résultat : "5.5"
NewFromFloat(546).RoundBank(-1).String() // Résultat : "550"
NewFromFloat(5.55).RoundBank(1).String() // Résultat : "5.6"
NewFromFloat(555).RoundBank(-1).String() // Résultat : "560"
6.3. Arrondi Monétaire
Arrondi Monétaire (également connu sous le nom d'arrondi monétaire) arrondit le décimal à des intervalles spécifiques. Le montant payable d'une transaction en espèces sera arrondi au multiple le plus proche de l'unité monétaire la plus petite. Les intervalles disponibles sont : 5, 10, 25, 50 et 100 ; tout autre nombre entraînera une exception.
5: arrondi à 5 cents 3.43 => 3.45
10: arrondi à 10 cents 3.45 => 3.50 (5 est arrondi vers le haut)
25: arrondi à 25 cents 3.41 => 3.50
50: arrondi à 50 cents 3.75 => 4.00
100: arrondi à 100 cents 3.50 => 4.00
6.4. Arrondi par Excès (RoundCeil)
Arrondi par Excès arrondit le décimal vers l'infini positif.
NewFromFloat(545).RoundCeil(-2).String() // Résultat : "600"
NewFromFloat(500).RoundCeil(-2).String() // Résultat : "500"
NewFromFloat(1.1001).RoundCeil(2).String() // Résultat : "1.11"
NewFromFloat(-1.454).RoundCeil(1).String() // Résultat : "-1.5"
6.5. Arrondi par Défaut (RoundDown)
Arrondi par Défaut arrondit le décimal vers zéro.
NewFromFloat(545).RoundDown(-2).String() // Résultat : "500"
NewFromFloat(-500).RoundDown(-2).String() // Résultat : "-500"
NewFromFloat(1.1001).RoundDown(2).String() // Résultat : "1.1"
NewFromFloat(-1.454).RoundDown(1).String() // Résultat : "-1.5"
6.6. RoundFloor
RoundFloor arrondit le décimal vers moins l'infini.
NewFromFloat(545).RoundFloor(-2).String() // Sortie: "500"
NewFromFloat(-500).RoundFloor(-2).String() // Sortie: "-500"
NewFromFloat(1.1001).RoundFloor(2).String() // Sortie: "1.1"
NewFromFloat(-1.454).RoundFloor(1).String() // Sortie: "-1.4"
6.7. RoundUp
RoundUp arrondit le décimal loin de zéro.
NewFromFloat(545).RoundUp(-2).String() // Sortie: "600"
NewFromFloat(500).RoundUp(-2).String() // Sortie: "500"
NewFromFloat(1.1001).RoundUp(2).String() // Sortie: "1.11"
NewFromFloat(-1.454).RoundUp(1).String() // Sortie: "-1.4"
7. Convertir le type Decimal en chaîne de caractères
La bibliothèque Decimal de Go fournit des méthodes pour convertir les valeurs décimales en représentations de chaîne de caractères. Voici quelques méthodes disponibles :
-
String(): string
: Renvoie la représentation de chaîne de caractères du nombre décimal avec un point décimal fixe. -
StringFixed(places int32) string
: Renvoie la représentation de chaîne arrondie avec un nombre spécifié de décimales. -
StringFixedBank(places int32) string
: Renvoie la représentation de chaîne arrondie (arrondi du banquier) avec un nombre spécifié de décimales.
Vous pouvez choisir la méthode appropriée selon vos besoins. Voici un exemple de conversion d'un nombre décimal en chaîne de caractères :
d := decimal.NewFromFloat(5.45)
str := d.String()
fmt.Println("Représentation de chaîne du nombre décimal:", str) // Représentation de chaîne du nombre décimal: 5.45
// Exemple de StringFixed
NewFromFloat(0).StringFixed(2) // Sortie: "0.00"
NewFromFloat(0).StringFixed(0) // Sortie: "0"
NewFromFloat(5.45).StringFixed(0) // Sortie: "5"
NewFromFloat(5.45).StringFixed(1) // Sortie: "5.5"
NewFromFloat(5.45).StringFixed(2) // Sortie: "5.45"
NewFromFloat(5.45).StringFixed(3) // Sortie: "5.450"
NewFromFloat(545).StringFixed(-1) // Sortie: "550"
// Exemple de StringFixedBank
NewFromFloat(0).StringFixedBank(2) // Sortie: "0.00"
NewFromFloat(0).StringFixedBank(0) // Sortie: "0"
NewFromFloat(5.45).StringFixedBank(0) // Sortie: "5"
NewFromFloat(5.45).StringFixedBank(1) // Sortie: "5.4"
NewFromFloat(5.45).StringFixedBank(2) // Sortie: "5.45"
NewFromFloat(5.45).StringFixedBank(3) // Sortie: "5.450"
NewFromFloat(545).StringFixedBank(-1) // Sortie: "540"
8. Questions courantes
Q: Pourquoi ne pas utiliser directement float64? R: float64 ne peut pas représenter avec précision des nombres comme 0.1, ce qui peut entraîner de petites erreurs. Dans les situations impliquant des calculs financiers, ces erreurs peuvent s'accumuler avec le temps et causer des problèmes significatifs.
Q: Pourquoi ne pas utiliser big.Rat directement? R: Bien que big.Rat puisse représenter des nombres rationnels, il n'est pas adapté pour représenter la monnaie. Les nombres décimaux sont meilleurs pour les calculs financiers car ils peuvent représenter avec précision les fractions décimales sans perdre de précision.
Q: Pourquoi l'API n'est-elle pas similaire à celle de big.Int? R: L'API de la bibliothèque Decimal privilégie la facilité d'utilisation et la correction par rapport aux performances. Alors que l'API de big.Int réduit les allocations de mémoire pour des raisons de performances, cela peut conduire à un code complexe et sujet aux erreurs. L'API de la bibliothèque Decimal est conçue pour être simple et facile à comprendre.