Skip to content

decimal

Kho lưu trữ: shopspring/decimal: Arbitrary-precision fixed-point decimal numbers in go (github.com)

Tài liệu: decimal package - github.com/shopspring/decimal - Go Packages

Giới thiệu

Một thư viện số thập phân dấu phẩy động được viết bằng Go, có các đặc điểm sau:

  • Giá trị 0 mặc định, có thể sử dụng an toàn mà không cần khởi tạo
  • Phép cộng, trừ, nhân không mất độ chính xác
  • Phép chia với độ chính xác chỉ định
  • Serialization/deserialization database/sql
  • Serialization/deserialization JSON và XML

Cài đặt

go get github.com/shopspring/decimal

Bắt đầu nhanh

go
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("Pre-tax:", preTax)                         // Pre-tax: 422.3421
  fmt.Println("Taxes:", total.Sub(preTax))                // Taxes: 37.482861375
  fmt.Println("Total:", total)                            // Total: 459.824961375
  fmt.Println("Tax rate:", total.Sub(preTax).Div(preTax)) // Tax rate: 0.08875
}

Các phương thức hữu ích

go
// Tạo từ chuỗi
func NewFromString(value string) (Decimal, error)

// Tạo từ float64
func NewFromFloat(value float64) Decimal

// Tạo từ int64
func NewFromInt(value int64) Decimal

// Tạo từ int32
func NewFromInt32(value int32) Decimal

// Cộng
func (d Decimal) Add(d2 Decimal) Decimal

// Trừ
func (d Decimal) Sub(d2 Decimal) Decimal

// Nhân
func (d Decimal) Mul(d2 Decimal) Decimal

// Chia
func (d Decimal) Div(d2 Decimal) Decimal

// Chia với độ chính xác
func (d Decimal) DivRound(d2 Decimal, precision int32) Decimal

// Làm tròn
func (d Decimal) Round(places int32) Decimal

// So sánh
func (d Decimal) Equal(d2 Decimal) bool
func (d Decimal) GreaterThan(d2 Decimal) bool
func (d Decimal) LessThan(d2 Decimal) bool

// Giá trị tuyệt đối
func (d Decimal) Abs() Decimal

// Đảo dấu
func (d Decimal) Negate() Decimal

// Chuyển đổi thành float64
func (d Decimal) Float64() (float64, error)

// Chuyển đổi thành int64
func (d Decimal) Int64() (int64, error)

// Chuyển đổi thành chuỗi
func (d Decimal) String() string

// MarshalJSON
func (d Decimal) MarshalJSON() ([]byte, error)

// UnmarshalJSON
func (d *Decimal) UnmarshalJSON(data []byte) error

Ví dụ bổ sung

go
package main

import (
    "fmt"
    "github.com/shopspring/decimal"
)

func main() {
    // Tạo decimal từ các kiểu khác nhau
    d1 := decimal.NewFromFloat(10.5)
    d2 := decimal.NewFromInt(3)
    d3, _ := decimal.NewFromString("5.25")
    
    // Các phép toán cơ bản
    fmt.Println("Cộng:", d1.Add(d2))      // 13.5
    fmt.Println("Trừ:", d1.Sub(d3))       // 5.25
    fmt.Println("Nhân:", d2.Mul(d3))      // 15.75
    fmt.Println("Chia:", d1.Div(d3))      // 2
    
    // Làm tròn
    d4 := decimal.NewFromFloat(10.123456)
    fmt.Println("Làm tròn 2:", d4.Round(2)) // 10.12
    fmt.Println("Làm tròn 4:", d4.Round(4)) // 10.1235
    
    // So sánh
    fmt.Println("So sánh bằng:", d1.Equal(d2)) // false
    fmt.Println("Lớn hơn:", d1.GreaterThan(d2)) // true
    
    // Giá trị tuyệt đối
    d5 := decimal.NewFromInt(-100)
    fmt.Println("Giá trị tuyệt đối:", d5.Abs()) // 100
}

Sử dụng với Database

go
package main

import (
    "database/sql"
    "github.com/shopspring/decimal"
)

type Product struct {
    ID    int
    Name  string
    Price decimal.Decimal
}

// Scan implements sql.Scanner interface
func (d *Decimal) Scan(value interface{}) error {
    // Implementation
}

// Value implements driver.Valuer interface
func (d Decimal) Value() (driver.Value, error) {
    // Implementation
}

Best Practices

  1. Sử dụng NewFromString: Ưu tiên sử dụng NewFromString để tránh mất độ chính xác với float
  2. Kiểm tra lỗi: Luôn kiểm tra lỗi khi tạo từ chuỗi
  3. Độ chính xác: Chỉ định độ chính xác phù hợp cho từng trường hợp sử dụng
  4. Performance: Decimal chậm hơn float64 nhưng đảm bảo độ chính xác
  5. Serialization: Hỗ trợ tốt cho JSON và database serialization

Kết luận

decimal là một thư viện hữu ích cho việc xử lý số thập phân trong Go, đặc biệt phù hợp cho các ứng dụng tài chính, kế toán nơi độ chính xác là yêu cầu bắt buộc. Với API đơn giản và nhiều tính năng hữu ích, decimal là lựa chọn tuyệt vời khi làm việc với số thập phân trong Go.

Golang by www.golangdev.cn edit