Skip to content

Commit

Permalink
Fix TruncateDecimal (#3913)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderbez authored Mar 16, 2019
1 parent 3d2886d commit 5f92fef
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#3870 Fix DecCoins#TruncateDecimal to never return zero coins in
either the truncated coins or the change coins.
21 changes: 11 additions & 10 deletions types/dec_coin.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ func (coin DecCoin) Sub(coinB DecCoin) DecCoin {
return DecCoin{coin.Denom, coin.Amount.Sub(coinB.Amount)}
}

// return the decimal coins with trunctated decimals, and return the change
// TruncateDecimal returns a Coin with a truncated decimal and a DecCoin for the
// change. Note, the change may be zero.
func (coin DecCoin) TruncateDecimal() (Coin, DecCoin) {
truncated := coin.Amount.TruncateInt()
change := coin.Amount.Sub(truncated.ToDec())
Expand Down Expand Up @@ -171,20 +172,20 @@ func (coins DecCoins) String() string {
}

// TruncateDecimal returns the coins with truncated decimals and returns the
// change.
func (coins DecCoins) TruncateDecimal() (Coins, DecCoins) {
changeSum := DecCoins{}
out := make(Coins, len(coins))

for i, coin := range coins {
// change. Note, it will not return any zero-amount coins in either the truncated or
// change coins.
func (coins DecCoins) TruncateDecimal() (truncatedCoins Coins, changeCoins DecCoins) {
for _, coin := range coins {
truncated, change := coin.TruncateDecimal()
out[i] = truncated
if !truncated.IsZero() {
truncatedCoins = truncatedCoins.Add(Coins{truncated})
}
if !change.IsZero() {
changeSum = changeSum.Add(DecCoins{change})
changeCoins = changeCoins.Add(DecCoins{change})
}
}

return out, changeSum
return truncatedCoins, changeCoins
}

// Add adds two sets of DecCoins.
Expand Down
36 changes: 35 additions & 1 deletion types/dec_coin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,40 @@ func TestDecCoinsIntersect(t *testing.T) {
require.NoError(t, err, "unexpected parse error in %v", i)

require.True(t, in1.Intersect(in2).IsEqual(exr), "in1.cap(in2) != exr in %v", i)
// require.Equal(t, tc.expectedResult, in1.Intersect(in2).String(), "in1.cap(in2) != exr in %v", i)
}
}

func TestDecCoinsTruncateDecimal(t *testing.T) {
decCoinA := NewDecCoinFromDec("bar", MustNewDecFromStr("5.41"))
decCoinB := NewDecCoinFromDec("foo", MustNewDecFromStr("6.00"))

testCases := []struct {
input DecCoins
truncatedCoins Coins
changeCoins DecCoins
}{
{DecCoins{}, Coins(nil), DecCoins(nil)},
{
DecCoins{decCoinA, decCoinB},
Coins{NewInt64Coin(decCoinA.Denom, 5), NewInt64Coin(decCoinB.Denom, 6)},
DecCoins{NewDecCoinFromDec(decCoinA.Denom, MustNewDecFromStr("0.41"))},
},
{
DecCoins{decCoinB},
Coins{NewInt64Coin(decCoinB.Denom, 6)},
DecCoins(nil),
},
}

for i, tc := range testCases {
truncatedCoins, changeCoins := tc.input.TruncateDecimal()
require.Equal(
t, tc.truncatedCoins, truncatedCoins,
"unexpected truncated coins; tc #%d, input: %s", i, tc.input,
)
require.Equal(
t, tc.changeCoins, changeCoins,
"unexpected change coins; tc #%d, input: %s", i, tc.input,
)
}
}
6 changes: 5 additions & 1 deletion types/decimal.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,10 @@ func (d Dec) Format(s fmt.State, verb rune) {
}

func (d Dec) String() string {
if d.Int == nil {
return d.Int.String()
}

isNeg := d.IsNegative()
if d.IsNegative() {
d = d.Neg()
Expand All @@ -348,7 +352,6 @@ func (d Dec) String() string {
// TODO: Remove trailing zeros
// case 1, purely decimal
if inputSize <= Precision {

bzStr = make([]byte, Precision+2)

// 0. prefix
Expand Down Expand Up @@ -377,6 +380,7 @@ func (d Dec) String() string {
if isNeg {
return "-" + string(bzStr)
}

return string(bzStr)
}

Expand Down

0 comments on commit 5f92fef

Please sign in to comment.