1. Einführung
Die Go Decimal-Bibliothek ist ein leistungsstarkes Werkzeug zur Behandlung von Dezimalzahlen mit beliebiger Präzision in der Go-Sprache. Sie ermöglicht Addition, Subtraktion, Multiplikation und Division ohne Genauigkeitsverlust. Darüber hinaus bietet sie Funktionen wie die Datenbank-/SQL-Serialisierung/Deserialisierung sowie die JSON-/XML-Serialisierung/Deserialisierung.
2. Installation
Um die Go Decimal-Bibliothek zu installieren, können Sie den folgenden Befehl verwenden:
go get github.com/shopspring/decimal
Bitte beachten Sie, dass die Decimal-Bibliothek Go Version >=1.7 erfordert.
3. Grundlegende Verwendung
Um die Decimal-Bibliothek in einem Go-Programm zu verwenden, importieren Sie das Paket "github.com/shopspring/decimal". Hier ist ein einfaches Beispiel, das die grundlegende Verwendung demonstriert:
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("Subtotal:", subtotal) // Subtotal: 408.06
fmt.Println("Vor Steuern:", preTax) // Vor Steuern: 422.3421
fmt.Println("Steuern:", total.Sub(preTax)) // Steuern: 37.482861375
fmt.Println("Gesamt:", total) // Gesamt: 459.824961375
fmt.Println("Steuersatz:", total.Sub(preTax).Div(preTax)) // Steuersatz: 0.08875
}
4. Erstellen von Dezimalvariablen
Die Decimal-Bibliothek bietet verschiedene Methoden zur Erstellung von Dezimalvariablen. Folgende APIs werden unterstützt:
-
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. Rechenoperationen
Die Go Decimal-Bibliothek bietet mehrere arithmetische Operationen, die auf Dezimalvariablen angewendet werden können. Hier sind einige unterstützte Operationen:
-
Add(d2 Decimal) Decimal
: Addiert zwei Dezimalwerte und gibt das Ergebnis zurück. -
Sub(d2 Decimal) Decimal
: Subtrahiert einen Dezimalwert von einem anderen und gibt das Ergebnis zurück. -
Div(d2 Decimal) Decimal
: Teilt einen Dezimalwert durch einen anderen und gibt das Ergebnis zurück. -
DivRound(d2 Decimal, precision int32) Decimal
: Teilt einen Dezimalwert durch einen anderen und gibt das Ergebnis mit bestimmter Genauigkeit zurück. -
Mod(d2 Decimal) Decimal
: Berechnet den Modulus (Rest) der Division eines Dezimalwerts durch einen anderen und gibt das Ergebnis zurück. -
Mul(d2 Decimal) Decimal
: Multipliziert zwei Dezimalwerte und gibt das Ergebnis zurück.
Mit diesen Operationen können gängige arithmetische Berechnungen mit Dezimalwerten durchgeführt werden. Hier ist ein Beispiel, das die Verwendung dieser Operationen demonstriert:
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("Subtotal:", subtotal) // Subtotal: 408.06
fmt.Println("Steuern:", tax) // Steuern: 36.244985
fmt.Println("Gesamt:", total) // Gesamt: 444.304985
Im obigen Beispiel wird die Methode Mul()
verwendet, um subtotal
zu berechnen, indem price
und quantity
multipliziert werden. Anschließend berechnen wir tax
, indem subtotal
mit dem Steuersatz multipliziert wird. Schließlich berechnen wir total
, indem wir subtotal
und tax
mit der Methode Add()
addieren.
6. Rundungsvorgänge
Die Go Decimal-Bibliothek bietet mehrere Rundungsvorgänge, die verwendet werden können, um Dezimalwerte auf eine bestimmte Genauigkeit zu runden. Hier sind einige verfügbare Rundungsvorgänge:
-
Round(places int32) Decimal
: Rundet die Dezimalzahl auf die angegebene Anzahl von Dezimalstellen. -
RoundBank(places int32) Decimal
: Rundet die Dezimalzahl mit dem Bankrundungsverfahren auf die angegebene Anzahl von Dezimalstellen. -
RoundCash(interval uint8) Decimal
: Rundet die Dezimalzahl auf ein spezifisches Intervall, wie z.B. 5 Cent, 10 Cent, 25 Cent, 50 Cent oder 1 Dollar. -
RoundCeil(places int32) Decimal
: Rundet die Dezimalzahl zur positiven Unendlichkeit. -
RoundDown(places int32) Decimal
: Rundet die Dezimalzahl zur Null hin ab. -
RoundFloor(places int32) Decimal
: Rundet die Dezimalzahl zur negativen Unendlichkeit. -
RoundUp(places int32) Decimal
: Rundet die Dezimalzahl von Null weg.
6.1. Runde
Runde rundet die Dezimalzahl auf die angegebene Anzahl von Dezimalstellen. Wenn places < 0 ist, rundet es den ganzzahligen Teil auf die nächste 10^(-places).
NewFromFloat(5.45).Round(1).String() // Ausgabe: "5,5"
NewFromFloat(545).Round(-1).String() // Ausgabe: "550"
6.2. RoundBank
RoundBank rundet die Dezimalzahl auf places Dezimalstellen. Wenn der Abstand zwischen der letzten zu rundenden Ziffer und den beiden nächstgelegenen ganzen Zahlen gleich ist, nimmt der gerundete Wert die gerade Zahl.
Wenn places < 0 ist, wird der ganze Teil auf das nächste 10^(-places) gerundet.
NewFromFloat(5.45).RoundBank(1).String() // Ausgabe: "5,4"
NewFromFloat(545).RoundBank(-1).String() // Ausgabe: "540"
NewFromFloat(5.46).RoundBank(1).String() // Ausgabe: "5,5"
NewFromFloat(546).RoundBank(-1).String() // Ausgabe: "550"
NewFromFloat(5.55).RoundBank(1).String() // Ausgabe: "5,6"
NewFromFloat(555).RoundBank(-1).String() // Ausgabe: "560"
6.3. RoundCash
RoundCash (auch bekannt als Cash/Penny/Irish-Rundung) rundet die Dezimalzahl auf spezifische Intervalle. Der zahlbare Betrag einer Bargeldtransaktion wird auf das nächste Vielfache der kleinsten Währungseinheit gerundet. Verfügbare Intervalle sind: 5, 10, 25, 50 und 100; jede andere Zahl führt zu einer Ausnahme.
5: 5-Cent-Rundung 3,43 => 3,45
10: 10-Cent-Rundung 3,45 => 3,50 (5 wird aufgerundet)
25: 25-Cent-Rundung 3,41 => 3,50
50: 50-Cent-Rundung 3,75 => 4,00
100: 100-Cent-Rundung 3,50 => 4,00
6.4. RoundCeil
RoundCeil rundet die Dezimalzahl zur positiven Unendlichkeit.
NewFromFloat(545).RoundCeil(-2).String() // Ausgabe: "600"
NewFromFloat(500).RoundCeil(-2).String() // Ausgabe: "500"
NewFromFloat(1.1001).RoundCeil(2).String() // Ausgabe: "1,11"
NewFromFloat(-1.454).RoundCeil(1).String() // Ausgabe: "-1,5"
6.5. RoundDown
RoundDown rundet die Dezimalzahl zur Null hin ab.
NewFromFloat(545).RoundDown(-2).String() // Ausgabe: "500"
NewFromFloat(-500).RoundDown(-2).String() // Ausgabe: "-500"
NewFromFloat(1.1001).RoundDown(2).String() // Ausgabe: "1,1"
NewFromFloat(-1.454).RoundDown(1).String() // Ausgabe: "-1,5"
6.6. RoundFloor
RoundFloor rundet die Dezimalzahl in Richtung negativer Unendlichkeit.
NewFromFloat(545).RoundFloor(-2).String() // Ausgabe: "500"
NewFromFloat(-500).RoundFloor(-2).String() // Ausgabe: "-500"
NewFromFloat(1.1001).RoundFloor(2).String() // Ausgabe: "1.1"
NewFromFloat(-1.454).RoundFloor(1).String() // Ausgabe: "-1.4"
6.7. RoundUp
RoundUp rundet die Dezimalzahl weg von Null.
NewFromFloat(545).RoundUp(-2).String() // Ausgabe: "600"
NewFromFloat(500).RoundUp(-2).String() // Ausgabe: "500"
NewFromFloat(1.1001).RoundUp(2).String() // Ausgabe: "1.11"
NewFromFloat(-1.454).RoundUp(1).String() // Ausgabe: "-1.4"
7. Konvertierung des Dezimaltyps in einen String
Die Go Decimal-Bibliothek bietet Methoden zur Konvertierung von Dezimalwerten in Zeichenketten. Hier sind einige verfügbare Methoden:
-
String(): string
: Gibt die Zeichenkettenrepräsentation der Dezimalzahl mit fester Dezimalstelle zurück. -
StringFixed(places int32) string
: Gibt die gerundete Zeichenkettenrepräsentation mit einer angegebenen Anzahl von Dezimalstellen zurück. -
StringFixedBank(places int32) string
: Gibt die gerundete (Bankers Rundung) Zeichenkettenrepräsentation mit einer angegebenen Anzahl von Dezimalstellen zurück.
Je nach Bedarf können Sie die geeignete Methode auswählen. Im Folgenden finden Sie ein Beispiel zur Konvertierung einer Dezimalzahl in eine Zeichenkette:
d := decimal.NewFromFloat(5.45)
str := d.String()
fmt.Println("Zeichenkettenrepräsentation der Dezimalzahl:", str) // Zeichenkettenrepräsentation der Dezimalzahl: 5.45
// Beispiel für StringFixed
NewFromFloat(0).StringFixed(2) // Ausgabe: "0.00"
NewFromFloat(0).StringFixed(0) // Ausgabe: "0"
NewFromFloat(5.45).StringFixed(0) // Ausgabe: "5"
NewFromFloat(5.45).StringFixed(1) // Ausgabe: "5.5"
NewFromFloat(5.45).StringFixed(2) // Ausgabe: "5.45"
NewFromFloat(5.45).StringFixed(3) // Ausgabe: "5.450"
NewFromFloat(545).StringFixed(-1) // Ausgabe: "550"
// Beispiel für StringFixedBank
NewFromFloat(0).StringFixedBank(2) // Ausgabe: "0.00"
NewFromFloat(0).StringFixedBank(0) // Ausgabe: "0"
NewFromFloat(5.45).StringFixedBank(0) // Ausgabe: "5"
NewFromFloat(5.45).StringFixedBank(1) // Ausgabe: "5.4"
NewFromFloat(5.45).StringFixedBank(2) // Ausgabe: "5.45"
NewFromFloat(5.45).StringFixedBank(3) // Ausgabe: "5.450"
NewFromFloat(545).StringFixedBank(-1) // Ausgabe: "540"
8. Häufig gestellte Fragen
F: Warum nicht float64 direkt verwenden? A: float64 kann Zahlen wie 0.1 nicht genau darstellen, was zu kleinen Fehlern führen kann. In Situationen, die finanzielle Berechnungen beinhalten, können sich diese Fehler im Laufe der Zeit ansammeln und zu erheblichen Problemen führen.
F: Warum nicht big.Rat direkt verwenden? A: Obwohl big.Rat rationale Zahlen darstellen kann, ist es nicht für die Darstellung von Währungen geeignet. Dezimalzahlen eignen sich besser für finanzielle Berechnungen, da sie Dezimalbrüche genau darstellen können, ohne an Präzision zu verlieren.
F: Warum ist die API nicht ähnlich wie bei big.Int? A: Die API der Decimal-Bibliothek priorisiert Benutzerfreundlichkeit und Korrektheit gegenüber Leistung. Während die API von big.Int aus Leistungsgründen Speicherzuweisungen reduziert, kann dies zu komplexem und fehleranfälligem Code führen. Die API der Decimal-Bibliothek ist darauf ausgelegt, einfach und leicht verständlich zu sein.