Merge PR #3315: Increase decimal precision to 18
* Decimal precision increase WIP * fix String() * resolve many errors * changelog
This commit is contained in:
parent
f2e87ad81f
commit
d9e32e93d5
@ -31,6 +31,7 @@ BREAKING CHANGES
|
||||
* [\#2222] [x/staking] `/stake` -> `/staking` module rename
|
||||
* \#3292 [x/distribution] Enable or disable withdraw addresses with a parameter in the param store
|
||||
* [staking] \#1402 Redelegation and unbonding-delegation structs changed to include multiple an array of entries
|
||||
* [\#3315] Increase decimal precision to 18
|
||||
|
||||
* Tendermint
|
||||
* [\#3298](https://github.com/cosmos/cosmos-sdk/issues/3298) Upgrade to Tendermint 0.28.0
|
||||
|
||||
@ -499,7 +499,7 @@ func TestBonding(t *testing.T) {
|
||||
// query delegations, unbondings and redelegations from validator and delegator
|
||||
delegatorDels = getDelegatorDelegations(t, port, addr)
|
||||
require.Len(t, delegatorDels, 1)
|
||||
require.Equal(t, "30.0000000000", delegatorDels[0].GetShares().String())
|
||||
require.Equal(t, "30.000000000000000000", delegatorDels[0].GetShares().String())
|
||||
|
||||
redelegation := getRedelegations(t, port, addr, operAddrs[0], operAddrs[1])
|
||||
require.Len(t, redelegation, 1)
|
||||
|
||||
@ -17,11 +17,11 @@ type Dec struct {
|
||||
|
||||
// number of decimal places
|
||||
const (
|
||||
Precision = 10
|
||||
Precision = 18
|
||||
|
||||
// bytes required to represent the above precision
|
||||
// ceil(log2(9999999999))
|
||||
DecimalPrecisionBits = 34
|
||||
// Ceiling[Log2[999 999 999 999 999 999]]
|
||||
DecimalPrecisionBits = 60
|
||||
)
|
||||
|
||||
var (
|
||||
@ -142,12 +142,14 @@ func NewDecFromStr(str string) (d Dec, err Error) {
|
||||
strs := strings.Split(str, ".")
|
||||
lenDecs := 0
|
||||
combinedStr := strs[0]
|
||||
if len(strs) == 2 {
|
||||
|
||||
if len(strs) == 2 { // has a decimal place
|
||||
lenDecs = len(strs[1])
|
||||
if lenDecs == 0 || len(combinedStr) == 0 {
|
||||
return d, ErrUnknownRequest("bad decimal length")
|
||||
}
|
||||
combinedStr = combinedStr + strs[1]
|
||||
|
||||
} else if len(strs) > 2 {
|
||||
return d, ErrUnknownRequest("too many periods to be a decimal string")
|
||||
}
|
||||
@ -162,7 +164,7 @@ func NewDecFromStr(str string) (d Dec, err Error) {
|
||||
zeros := fmt.Sprintf(`%0`+strconv.Itoa(zerosToAdd)+`s`, "")
|
||||
combinedStr = combinedStr + zeros
|
||||
|
||||
combined, ok := new(big.Int).SetString(combinedStr, 10)
|
||||
combined, ok := new(big.Int).SetString(combinedStr, 10) // base 10
|
||||
if !ok {
|
||||
return d, ErrUnknownRequest(fmt.Sprintf("bad string to integer conversion, combinedStr: %v", combinedStr))
|
||||
}
|
||||
@ -276,36 +278,48 @@ func (d Dec) String() string {
|
||||
if d.IsNegative() {
|
||||
d = d.Neg()
|
||||
}
|
||||
bz, err := d.Int.MarshalText()
|
||||
|
||||
bzInt, err := d.Int.MarshalText()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
var bzWDec []byte
|
||||
inputSize := len(bz)
|
||||
inputSize := len(bzInt)
|
||||
|
||||
var bzStr []byte
|
||||
|
||||
// TODO: Remove trailing zeros
|
||||
// case 1, purely decimal
|
||||
if inputSize <= 10 {
|
||||
bzWDec = make([]byte, 12)
|
||||
if inputSize <= Precision {
|
||||
|
||||
bzStr = make([]byte, Precision+2)
|
||||
|
||||
// 0. prefix
|
||||
bzWDec[0] = byte('0')
|
||||
bzWDec[1] = byte('.')
|
||||
bzStr[0] = byte('0')
|
||||
bzStr[1] = byte('.')
|
||||
|
||||
// set relevant digits to 0
|
||||
for i := 0; i < 10-inputSize; i++ {
|
||||
bzWDec[i+2] = byte('0')
|
||||
for i := 0; i < Precision-inputSize; i++ {
|
||||
bzStr[i+2] = byte('0')
|
||||
}
|
||||
// set last few digits
|
||||
copy(bzWDec[2+(10-inputSize):], bz)
|
||||
|
||||
// set final digits
|
||||
copy(bzStr[2+(Precision-inputSize):], bzInt)
|
||||
|
||||
} else {
|
||||
|
||||
// inputSize + 1 to account for the decimal point that is being added
|
||||
bzWDec = make([]byte, inputSize+1)
|
||||
copy(bzWDec, bz[:inputSize-10])
|
||||
bzWDec[inputSize-10] = byte('.')
|
||||
copy(bzWDec[inputSize-9:], bz[inputSize-10:])
|
||||
bzStr = make([]byte, inputSize+1)
|
||||
decPointPlace := inputSize - Precision
|
||||
|
||||
copy(bzStr, bzInt[:decPointPlace]) // pre-decimal digits
|
||||
bzStr[decPointPlace] = byte('.') // decimal point
|
||||
copy(bzStr[decPointPlace+1:], bzInt[decPointPlace:]) // post-decimal digits
|
||||
}
|
||||
|
||||
if isNeg {
|
||||
return "-" + string(bzWDec)
|
||||
return "-" + string(bzStr)
|
||||
}
|
||||
return string(bzWDec)
|
||||
return string(bzStr)
|
||||
}
|
||||
|
||||
// ____
|
||||
|
||||
@ -22,7 +22,7 @@ func mustNewDecFromStr(t *testing.T, str string) (d Dec) {
|
||||
|
||||
func TestPrecisionMultiplier(t *testing.T) {
|
||||
res := precisionMultiplier(5)
|
||||
exp := big.NewInt(100000)
|
||||
exp := big.NewInt(10000000000000)
|
||||
require.Equal(t, 0, res.Cmp(exp), "equality was incorrect, res %v, exp %v", res, exp)
|
||||
}
|
||||
|
||||
@ -76,6 +76,25 @@ func TestNewDecFromStr(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecString(t *testing.T) {
|
||||
tests := []struct {
|
||||
d Dec
|
||||
want string
|
||||
}{
|
||||
{NewDec(0), "0.000000000000000000"},
|
||||
{NewDec(1), "1.000000000000000000"},
|
||||
{NewDec(10), "10.000000000000000000"},
|
||||
{NewDec(12340), "12340.000000000000000000"},
|
||||
{NewDecWithPrec(12340, 4), "1.234000000000000000"},
|
||||
{NewDecWithPrec(12340, 5), "0.123400000000000000"},
|
||||
{NewDecWithPrec(12340, 8), "0.000123400000000000"},
|
||||
{NewDecWithPrec(1009009009009009009, 17), "10.090090090090090090"},
|
||||
}
|
||||
for tcIndex, tc := range tests {
|
||||
assert.Equal(t, tc.want, tc.d.String(), "bad String(), index: %v", tcIndex)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEqualities(t *testing.T) {
|
||||
tests := []struct {
|
||||
d1, d2 Dec
|
||||
@ -140,7 +159,7 @@ func TestArithmetic(t *testing.T) {
|
||||
d1, d2 Dec
|
||||
expMul, expDiv, expAdd, expSub Dec
|
||||
}{
|
||||
// d1 d2 MUL DIV ADD SUB
|
||||
// d1 d2 MUL DIV ADD SUB
|
||||
{NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(0)},
|
||||
{NewDec(1), NewDec(0), NewDec(0), NewDec(0), NewDec(1), NewDec(1)},
|
||||
{NewDec(0), NewDec(1), NewDec(0), NewDec(0), NewDec(1), NewDec(-1)},
|
||||
@ -152,14 +171,14 @@ func TestArithmetic(t *testing.T) {
|
||||
{NewDec(1), NewDec(-1), NewDec(-1), NewDec(-1), NewDec(0), NewDec(2)},
|
||||
{NewDec(-1), NewDec(1), NewDec(-1), NewDec(-1), NewDec(0), NewDec(-2)},
|
||||
|
||||
{NewDec(3), NewDec(7), NewDec(21), NewDecWithPrec(4285714286, 10), NewDec(10), NewDec(-4)},
|
||||
{NewDec(3), NewDec(7), NewDec(21), NewDecWithPrec(428571428571428571, 18), NewDec(10), NewDec(-4)},
|
||||
{NewDec(2), NewDec(4), NewDec(8), NewDecWithPrec(5, 1), NewDec(6), NewDec(-2)},
|
||||
{NewDec(100), NewDec(100), NewDec(10000), NewDec(1), NewDec(200), NewDec(0)},
|
||||
|
||||
{NewDecWithPrec(15, 1), NewDecWithPrec(15, 1), NewDecWithPrec(225, 2),
|
||||
NewDec(1), NewDec(3), NewDec(0)},
|
||||
{NewDecWithPrec(3333, 4), NewDecWithPrec(333, 4), NewDecWithPrec(1109889, 8),
|
||||
NewDecWithPrec(10009009009, 9), NewDecWithPrec(3666, 4), NewDecWithPrec(3, 1)},
|
||||
MustNewDecFromStr("10.009009009009009009"), NewDecWithPrec(3666, 4), NewDecWithPrec(3, 1)},
|
||||
}
|
||||
|
||||
for tcIndex, tc := range tests {
|
||||
@ -245,14 +264,14 @@ func TestDecMarshalJSON(t *testing.T) {
|
||||
want string
|
||||
wantErr bool // if wantErr = false, will also attempt unmarshaling
|
||||
}{
|
||||
{"zero", decimal(0), "\"0.0000000000\"", false},
|
||||
{"one", decimal(1), "\"0.0000000001\"", false},
|
||||
{"ten", decimal(10), "\"0.0000000010\"", false},
|
||||
{"12340", decimal(12340), "\"0.0000012340\"", false},
|
||||
{"zeroInt", NewDec(0), "\"0.0000000000\"", false},
|
||||
{"oneInt", NewDec(1), "\"1.0000000000\"", false},
|
||||
{"tenInt", NewDec(10), "\"10.0000000000\"", false},
|
||||
{"12340Int", NewDec(12340), "\"12340.0000000000\"", false},
|
||||
{"zero", decimal(0), "\"0.000000000000000000\"", false},
|
||||
{"one", decimal(1), "\"0.000000000000000001\"", false},
|
||||
{"ten", decimal(10), "\"0.000000000000000010\"", false},
|
||||
{"12340", decimal(12340), "\"0.000000000000012340\"", false},
|
||||
{"zeroInt", NewDec(0), "\"0.000000000000000000\"", false},
|
||||
{"oneInt", NewDec(1), "\"1.000000000000000000\"", false},
|
||||
{"tenInt", NewDec(10), "\"10.000000000000000000\"", false},
|
||||
{"12340Int", NewDec(12340), "\"12340.000000000000000000\"", false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
@ -344,7 +363,7 @@ func TestStringOverflow(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
dec3 := dec1.Add(dec2)
|
||||
require.Equal(t,
|
||||
"19844653375691057515930281852116324640.0000000000",
|
||||
"19844653375691057515930281852116324640.000000000000000000",
|
||||
dec3.String(),
|
||||
)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user