Missing feature of the Go standard library: parsing and formatting int64 as a fractional numeric string, without any rounding or bignums, by using a fixed fraction size. Supports arbitrary radixes from 2 to 36.
For example:
"123" <- frac 2, radix 10 -> 123_00
"123" <- frac 3, radix 10 -> 123_000
"123.45" <- frac 2, radix 10 -> 123_45
"123.45" <- frac 3, radix 10 -> 123_450
"123.456" <- frac 2, radix 10 -> <error>
"123.456" <- frac 3, radix 10 -> 123_456
Performance on 64-bit machines is somewhat comparable to strconv and shouldn't be your bottleneck.
See API docs at https://pkg.go.dev/github.com/mitranim/frac.
- You use integers for money.
- You deal with external APIs that use decimal strings for money.
- You want to avoid rounding errors.
- You don't want to deal with "big decimal" libraries.
Then frac is for you!
Basic usage:
import "github.com/mitranim/frac"
func main() {
num, err := frac.ParseDec(`-123`, 2)
assert(err == nil && num == -123_00)
num, err = frac.ParseDec(`-123.00`, 2)
assert(err == nil && num == -123_00)
num, err = frac.ParseDec(`-123.45`, 2)
assert(err == nil && num == -123_45)
// Exponent exceeds allotted precision. Conversion is impossible.
num, err = frac.ParseDec(`-123.456`, 2)
assert(err != nil && num == 0)
}
func assert(ok bool) {if !ok {panic("unreachable")}}Implementing a monetary type:
import "github.com/mitranim/frac"
type Cents int64
func (self *Cents) UnmarshalText(input []byte) error {
num, err := frac.UnmarshalDec(input, 2)
if err != nil {
return err
}
*self = Cents(num)
return nil
}
func (self Cents) MarshalText() ([]byte, error) {
return frac.AppendDec(nil, int64(self), 2)
}The resulting type Cents is an integer, but when decoding and encoding text, it's represented as a fractional with 2 decimal points.
-
The code is too assembly-like. Kinda like the standard library.
-
No special support for unsigned integers.
-
When formatting, fractional precision is limited to
64. (Imagine allocating gigabytes of memory for0.0...01.)
I'm receptive to suggestions. If this library almost satisfies you but needs changes, open an issue or chat me up. Contacts: https://mitranim.com/#contacts