Skip to content

Commit

Permalink
Merge PR #3315: Increase decimal precision to 18
Browse files Browse the repository at this point in the history
* Decimal precision increase WIP
* fix String()
* resolve many errors
* changelog
  • Loading branch information
rigelrozanski authored and cwgoes committed Jan 17, 2019
1 parent f2e87ad commit d9e32e9
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 36 deletions.
1 change: 1 addition & 0 deletions PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion client/lcd/lcd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
58 changes: 36 additions & 22 deletions types/decimal.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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")
}
Expand All @@ -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))
}
Expand Down Expand Up @@ -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)
}

// ____
Expand Down
45 changes: 32 additions & 13 deletions types/decimal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)},
Expand All @@ -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 {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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(),
)
}
Expand Down

0 comments on commit d9e32e9

Please sign in to comment.