Fix TruncateDecimal (#3913)
This commit is contained in:
parent
3d2886dc49
commit
5f92fef4b0
@ -0,0 +1,2 @@
|
||||
#3870 Fix DecCoins#TruncateDecimal to never return zero coins in
|
||||
either the truncated coins or the change coins.
|
||||
@ -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())
|
||||
@ -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.
|
||||
|
||||
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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()
|
||||
@ -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
|
||||
@ -377,6 +380,7 @@ func (d Dec) String() string {
|
||||
if isNeg {
|
||||
return "-" + string(bzStr)
|
||||
}
|
||||
|
||||
return string(bzStr)
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user