Documentation ¶
Overview ¶
Handling floating point numbers in programming causes rounding errors. To avoid this, all numerical calculations are done using basis points (integer only) in this package.
Example ¶
package main import ( "fmt" "go.mercari.io/go-bps/bps" ) type Bill struct { Principal int64 Rate *bps.BPS } func NewBill(principal int64, rate *bps.BPS) *Bill { return &Bill{Principal: principal, Rate: rate} } // CalcInterestFee calculates an interest fee for `b` func (b *Bill) CalcInterestFee() *bps.BPS { return b.Rate.Mul(b.Principal) } type Bills []*Bill func (bl Bills) CalcInterestFee() *bps.BPS { var fees []*bps.BPS for _, b := range bl { fees = append(fees, b.CalcInterestFee()) } return bps.Sum(bps.NewFromAmount(0), fees...) } func main() { // principal amount is 14999 var principal int64 = 14999 // interest rate is 8.0% rate1 := bps.NewFromPercentage(8) // interest rate is 2.645% = 264.5 basis points = 2645 deci basis points rate2 := bps.NewFromDeciBasisPoint(2645) // interest rate is 4.5% rate3 := bps.MustFromString(".045") b1 := NewBill(principal, rate1) b2 := NewBill(principal, rate2) b3 := NewBill(principal, rate3) bills := Bills{b1, b2, b3} // interest fee: 14999 * 8% = 1199.92 // Amounts() returns fee amount as integer that's rounded off decimal floating point fmt.Println(b1.CalcInterestFee().FloatString(2)) // interest fee: 14999 * 2.645 = 396.72355 fmt.Println(b2.CalcInterestFee().FloatString(2)) // interest fee: 14999 * 4.5% = 674.955 fmt.Println(b3.CalcInterestFee().FloatString(2)) // sum interest fees: 1199.92 + 396.72355 + 674.955 = 2271.59855 // not equal 1199 + 396 + 674 = 2269 fmt.Println(bills.CalcInterestFee().FloatString(0)) }
Output: 1199.92 396.72 674.96 2272
Index ¶
- Constants
- Variables
- type BPS
- func Avg(first *BPS, rest ...*BPS) *BPS
- func Max(first *BPS, rest ...*BPS) *BPS
- func Min(fisrt *BPS, rest ...*BPS) *BPS
- func MustFromString(value string) *BPS
- func NewFromAmount(amt int64) *BPS
- func NewFromBaseUnit(v int64) *BPS
- func NewFromBasisPoint(bp int64) *BPS
- func NewFromDeciBasisPoint(deci int64) *BPS
- func NewFromHalfBasisPoint(bp int64) *BPS
- func NewFromPPB(ppb *big.Int) *BPS
- func NewFromPPM(ppm *big.Int) *BPS
- func NewFromPercentage(per int64) *BPS
- func NewFromString(value string) (*BPS, error)
- func Sum(first *BPS, rest ...*BPS) *BPS
- func (b *BPS) Abs() *BPS
- func (b *BPS) Add(b2 *BPS) *BPS
- func (b *BPS) Amounts() int64
- func (b *BPS) BaseUnitAmounts() *big.Int
- func (b *BPS) BasisPoints() *big.Int
- func (b *BPS) Cmp(b2 *BPS) int
- func (b *BPS) DeciBasisPoints() *big.Int
- func (b *BPS) Div(i int64) *BPS
- func (b *BPS) Equal(b2 *BPS) bool
- func (b *BPS) Float64() (f float64, exact bool)
- func (b *BPS) FloatString(prec int) string
- func (b *BPS) HalfBasisPoints() *big.Int
- func (b *BPS) IsZero() bool
- func (b *BPS) Mul(i int64) *BPS
- func (b *BPS) Neg() *BPS
- func (b *BPS) PPBs() *big.Int
- func (b *BPS) PPMs() *big.Int
- func (b *BPS) Percentages() *big.Int
- func (b *BPS) Rat() *big.Rat
- func (b *BPS) Scan(value interface{}) error
- func (b *BPS) String() string
- func (b *BPS) Sub(b2 *BPS) *BPS
- func (b *BPS) UnmarshalText(text []byte) error
- func (b *BPS) Value() (driver.Value, error)
Examples ¶
Constants ¶
const ( PPB unit = iota + 1 PPM DeciBasisPoint HalfBasisPoint BasisPoint Percentage )
List of values that `unit` can take.
const ( DenomPPM int64 = 1000 DenomDeciBasisPoint = DenomPPM * 10 DenomHalfBasisPoint = DenomDeciBasisPoint * 5 DenomBasisPoint = DenomHalfBasisPoint * 2 DenomPercentage = DenomBasisPoint * 100 DenomAmount = DenomPercentage * 100 )
Denominators for each parts
Variables ¶
var BaseUnit = DeciBasisPoint
BaseUnit is unit to display *BPS as string via String method. Default is DeciBasisPoint unit, you can update this. But it should be used consistent value in your application.
Functions ¶
This section is empty.
Types ¶
type BPS ¶
type BPS struct {
// contains filtered or unexported fields
}
func Max ¶
Max returns the largest BPS that was passed in the arguments.
To call this function with an array, you must do:
Max(arr[0], arr[1:]...)
This makes it harder to accidentally call Max with 0 arguments.
func Min ¶
Min returns the smallest BPS that was passed in the arguments.
To call this function with an array, you must do:
Min(arr[0], arr[1:]...)
This makes it harder to accidentally call Min with 0 arguments.
func MustFromString ¶
MustFromString returns a new BPS from a string representation or panics if NewFromString would have returned an error.
Example ¶
package main import ( "fmt" "go.mercari.io/go-bps/bps" ) func main() { // 15% b1 := bps.MustFromString("0.15") fmt.Println(b1.Percentages()) // 2.645% = 264.5 basis points b2 := bps.MustFromString("0.02645") fmt.Println(b2.DeciBasisPoints()) a := bps.NewFromAmount(1e12) b, _ := bps.NewFromString(".000001") // 1 / 1e6 // Set PPM as BaseUnit to show value as ppm bps.BaseUnit = bps.PPM fmt.Println(a.Add(b), "ppm") // teardown bps.BaseUnit = bps.DeciBasisPoint n := bps.NewFromAmount(0) for i := 0; i < 1000; i++ { n = n.Add(bps.MustFromString(".01")) } fmt.Println(n.Amounts()) }
Output: 15 2645 1000000000000000001 ppm 10
func NewFromAmount ¶
NewFromAmount makes new BPS instance from real amount
func NewFromBaseUnit ¶
NewFromBaseUnit makes new BPS instance from BaseUnit value. That means the effective digits is modifiable by BaseUnit.
Example ¶
package main import ( "fmt" "go.mercari.io/go-bps/bps" ) func main() { // backup u := bps.BaseUnit var arg int64 = 15 // The default BaseUnit is DeciBasisPoint deci := bps.NewFromBaseUnit(arg) fmt.Println(deci.PPMs()) // BaseUnit is updated by PPB bps.BaseUnit = bps.PPB ppb := bps.NewFromBaseUnit(arg) fmt.Println(ppb.PPBs()) // BaseUnit is updated by PPM bps.BaseUnit = bps.PPM ppm := bps.NewFromBaseUnit(arg) fmt.Println(ppm.PPBs()) // BaseUnit is updated by HalfBasisPoint bps.BaseUnit = bps.HalfBasisPoint hbp := bps.NewFromBaseUnit(arg) fmt.Println(hbp.PPBs()) // BaseUnit is updated by BasisPoint bps.BaseUnit = bps.BasisPoint bp := bps.NewFromBaseUnit(arg) fmt.Println(bp.PPBs()) // BaseUnit is updated by Percentage bps.BaseUnit = bps.Percentage p := bps.NewFromBaseUnit(arg) fmt.Println(p.PPBs()) // teardown bps.BaseUnit = u }
Output: 150 15 15000 750000 1500000 150000000
func NewFromBasisPoint ¶
NewFromBasisPoint makes new BPS instance from basis point
func NewFromDeciBasisPoint ¶
NewFromDeciBasisPoint makes new BPS instance from deci basis point
func NewFromHalfBasisPoint ¶
NewFromHalfBasisPoint makes new BPS instance from half basis point
func NewFromPPB ¶ added in v1.1.0
NewFromPPB makes new BPS instance from part per billion(ppb)
func NewFromPPM ¶
NewFromPPM makes new BPS instance from part per million(ppm)
func NewFromPercentage ¶
NewFromPercentage makes new BPS instance from percentage
func NewFromString ¶
NewFromString returns a new BPS from a string representation.
Example ¶
package main import ( "fmt" "go.mercari.io/go-bps/bps" ) func main() { // 15% b1, _ := bps.NewFromString("0.15") fmt.Println(b1.Percentages()) // 2.645% = 264.5 basis points b2, _ := bps.NewFromString("0.02645") fmt.Println(b2.DeciBasisPoints()) }
Output: 15 2645
func (*BPS) BaseUnitAmounts ¶
BaseUnitAmounts returns amount representation of BaseUnit as generated. That means the effective digits is modifiable by BaseUnit.
Example ¶
package main import ( "fmt" "go.mercari.io/go-bps/bps" ) func main() { // backup u := bps.BaseUnit // 15% b := bps.NewFromPercentage(15) // The default BaseUnit is DeciBasisPoint fmt.Println(b.BaseUnitAmounts()) // BaseUnit is updated by PPB bps.BaseUnit = bps.PPB fmt.Println(b.BaseUnitAmounts()) // BaseUnit is updated by PPM bps.BaseUnit = bps.PPM fmt.Println(b.BaseUnitAmounts()) // BaseUnit is updated by HalfBasisPoint bps.BaseUnit = bps.HalfBasisPoint fmt.Println(b.BaseUnitAmounts()) // BaseUnit is updated by BasisPoint bps.BaseUnit = bps.BasisPoint fmt.Println(b.BaseUnitAmounts()) // BaseUnit is updated by Percentage bps.BaseUnit = bps.Percentage fmt.Println(b.BaseUnitAmounts()) // teardown bps.BaseUnit = u }
Output: 15000 150000000 150000 3000 1500 15
func (*BPS) BasisPoints ¶
BasisPoints returns the basis point as an integer basis point count.
func (*BPS) DeciBasisPoints ¶
DeciBasisPoints returns the basis point as an integer half basis point count.
func (*BPS) Float64 ¶
Float64 returns the nearest float64 value for `b` and a bool indicating whether f represents `b` exactly. If the magnitude of `b` is too large to be represented by a float64, f is an infinity and exact is false. The sign of f always matches the sign of `b`, even if f == 0.
func (*BPS) FloatString ¶
FloatString returns the string representation of the amount as generated by *big.Rat.FloatString(prec)
func (*BPS) HalfBasisPoints ¶
HalfBasisPoints returns the basis point as an integer half basis point count.
func (*BPS) Percentages ¶
Percentages returns the basis point as an integer percentage count.
func (*BPS) String ¶
String returns the string representation of BaseUnit as generated by *big.Int.String(). That means the effective digits is modifiable by BaseUnit.
func (*BPS) UnmarshalText ¶ added in v1.1.1
UnmarshalText implements the encoding.TextUnmarshaler interface.