bps

package
Version: v1.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 25, 2021 License: MIT Imports: 8 Imported by: 1

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

Examples

Constants

View Source
const (
	PPB unit = iota + 1
	PPM
	DeciBasisPoint
	HalfBasisPoint
	BasisPoint
	Percentage
)

List of values that `unit` can take.

View Source
const (
	DenomPPM            int64 = 1000
	DenomDeciBasisPoint       = DenomPPM * 10
	DenomHalfBasisPoint       = DenomDeciBasisPoint * 5
	DenomBasisPoint           = DenomHalfBasisPoint * 2
	DenomPercentage           = DenomBasisPoint * 100
	DenomAmount               = DenomPercentage * 100
)

Denominators for each parts

Variables

View Source
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 Avg

func Avg(first *BPS, rest ...*BPS) *BPS

Avg returns the average value of the provided first and rest BPS

func Max

func Max(first *BPS, rest ...*BPS) *BPS

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

func Min(fisrt *BPS, rest ...*BPS) *BPS

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

func MustFromString(value string) *BPS

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

func NewFromAmount(amt int64) *BPS

NewFromAmount makes new BPS instance from real amount

func NewFromBaseUnit

func NewFromBaseUnit(v int64) *BPS

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

func NewFromBasisPoint(bp int64) *BPS

NewFromBasisPoint makes new BPS instance from basis point

func NewFromDeciBasisPoint

func NewFromDeciBasisPoint(deci int64) *BPS

NewFromDeciBasisPoint makes new BPS instance from deci basis point

func NewFromHalfBasisPoint

func NewFromHalfBasisPoint(bp int64) *BPS

NewFromHalfBasisPoint makes new BPS instance from half basis point

func NewFromPPB added in v1.1.0

func NewFromPPB(ppb *big.Int) *BPS

NewFromPPB makes new BPS instance from part per billion(ppb)

func NewFromPPM

func NewFromPPM(ppm *big.Int) *BPS

NewFromPPM makes new BPS instance from part per million(ppm)

func NewFromPercentage

func NewFromPercentage(per int64) *BPS

NewFromPercentage makes new BPS instance from percentage

func NewFromString

func NewFromString(value string) (*BPS, error)

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 Sum

func Sum(first *BPS, rest ...*BPS) *BPS

Sum returns the combined total of the provided first and rest BPS

func (*BPS) Abs

func (b *BPS) Abs() *BPS

Abs returns the absolute value of the decimal.

func (*BPS) Add

func (b *BPS) Add(b2 *BPS) *BPS

Add returns b + b2.

func (*BPS) Amounts

func (b *BPS) Amounts() int64

Amounts returns the basis point as an integer amount.

func (*BPS) BaseUnitAmounts

func (b *BPS) BaseUnitAmounts() *big.Int

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

func (b *BPS) BasisPoints() *big.Int

BasisPoints returns the basis point as an integer basis point count.

func (*BPS) Cmp

func (b *BPS) Cmp(b2 *BPS) int

func (*BPS) DeciBasisPoints

func (b *BPS) DeciBasisPoints() *big.Int

DeciBasisPoints returns the basis point as an integer half basis point count.

func (*BPS) Div

func (b *BPS) Div(i int64) *BPS

Div returns b / i, rounded down to ppm.

func (*BPS) Equal

func (b *BPS) Equal(b2 *BPS) bool

func (*BPS) Float64

func (b *BPS) Float64() (f float64, exact bool)

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

func (b *BPS) FloatString(prec int) string

FloatString returns the string representation of the amount as generated by *big.Rat.FloatString(prec)

func (*BPS) HalfBasisPoints

func (b *BPS) HalfBasisPoints() *big.Int

HalfBasisPoints returns the basis point as an integer half basis point count.

func (*BPS) IsZero

func (b *BPS) IsZero() bool

func (*BPS) Mul

func (b *BPS) Mul(i int64) *BPS

Mul returns b * i.

func (*BPS) Neg

func (b *BPS) Neg() *BPS

Neg returns -b.

func (*BPS) PPBs added in v1.1.0

func (b *BPS) PPBs() *big.Int

PPBs returns the row value that means PPB.

func (*BPS) PPMs

func (b *BPS) PPMs() *big.Int

PPMs returns the row value that means PPM.

func (*BPS) Percentages

func (b *BPS) Percentages() *big.Int

Percentages returns the basis point as an integer percentage count.

func (*BPS) Rat

func (b *BPS) Rat() *big.Rat

Rat returns a rational number representation of `b`.

func (*BPS) Scan

func (b *BPS) Scan(value interface{}) error

Scan implements the sql.Scanner interface for database deserialization.

func (*BPS) String

func (b *BPS) String() 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) Sub

func (b *BPS) Sub(b2 *BPS) *BPS

Sub returns b - b2.

func (*BPS) UnmarshalText added in v1.1.1

func (b *BPS) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface.

func (*BPS) Value

func (b *BPS) Value() (driver.Value, error)

Value implements the driver.Valuer interface for database serialization.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL