mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-22 19:29:39 +00:00
util: implement FixedN from string
When working with NEP5 contracts we frequently need to parse fixed-point decimals with arbitrary precision.
This commit is contained in:
parent
cdeba6d417
commit
d447064515
2 changed files with 30 additions and 4 deletions
|
@ -3,6 +3,7 @@ package util
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"math"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -71,25 +72,36 @@ func Fixed8FromFloat(val float64) Fixed8 {
|
||||||
// Fixed8FromString parses s which must be a fixed point number
|
// Fixed8FromString parses s which must be a fixed point number
|
||||||
// with precision up to 10^-8
|
// with precision up to 10^-8
|
||||||
func Fixed8FromString(s string) (Fixed8, error) {
|
func Fixed8FromString(s string) (Fixed8, error) {
|
||||||
|
num, err := FixedNFromString(s, precision)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return Fixed8(num), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// FixedNFromString parses s which must be a fixed point number
|
||||||
|
// with precision 10^-d.
|
||||||
|
func FixedNFromString(s string, precision int) (int64, error) {
|
||||||
parts := strings.SplitN(s, ".", 2)
|
parts := strings.SplitN(s, ".", 2)
|
||||||
|
d := int64(math.Pow10(precision))
|
||||||
ip, err := strconv.ParseInt(parts[0], 10, 64)
|
ip, err := strconv.ParseInt(parts[0], 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errInvalidString
|
return 0, errInvalidString
|
||||||
} else if len(parts) == 1 {
|
} else if len(parts) == 1 {
|
||||||
return Fixed8(ip * decimals), nil
|
return ip * d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
fp, err := strconv.ParseInt(parts[1], 10, 64)
|
fp, err := strconv.ParseInt(parts[1], 10, 64)
|
||||||
if err != nil || fp >= decimals {
|
if err != nil || fp >= d {
|
||||||
return 0, errInvalidString
|
return 0, errInvalidString
|
||||||
}
|
}
|
||||||
for i := len(parts[1]); i < precision; i++ {
|
for i := len(parts[1]); i < precision; i++ {
|
||||||
fp *= 10
|
fp *= 10
|
||||||
}
|
}
|
||||||
if ip < 0 {
|
if ip < 0 {
|
||||||
return Fixed8(ip*decimals - fp), nil
|
return ip*d - fp, nil
|
||||||
}
|
}
|
||||||
return Fixed8(ip*decimals + fp), nil
|
return ip*d + fp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements the json unmarshaller interface.
|
// UnmarshalJSON implements the json unmarshaller interface.
|
||||||
|
|
|
@ -85,6 +85,20 @@ func TestFixed8FromString(t *testing.T) {
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFixedNFromString(t *testing.T) {
|
||||||
|
val := "123.456"
|
||||||
|
num, err := FixedNFromString(val, 3)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.EqualValues(t, 123456, num)
|
||||||
|
|
||||||
|
num, err = FixedNFromString(val, 4)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.EqualValues(t, 1234560, num)
|
||||||
|
|
||||||
|
_, err = FixedNFromString(val, 2)
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func TestSatoshi(t *testing.T) {
|
func TestSatoshi(t *testing.T) {
|
||||||
satoshif8 := Satoshi()
|
satoshif8 := Satoshi()
|
||||||
assert.Equal(t, "0.00000001", satoshif8.String())
|
assert.Equal(t, "0.00000001", satoshif8.String())
|
||||||
|
|
Loading…
Reference in a new issue