diff --git a/numeric/decimal.go b/numeric/decimal.go index f80c9eca14..b29ca64d48 100644 --- a/numeric/decimal.go +++ b/numeric/decimal.go @@ -383,32 +383,45 @@ func (d Dec) String() string { var bzStr []byte - // TODO: Remove trailing zeros // case 1, purely decimal if inputSize <= Precision { - bzStr = make([]byte, Precision+2) + bzStr = make([]byte, 0, Precision+2) // 0. prefix - bzStr[0] = byte('0') - bzStr[1] = byte('.') - - // set relevant digits to 0 - for i := 0; i < Precision-inputSize; i++ { - bzStr[i+2] = byte('0') + bzStr = append(bzStr, byte('0')) + if !IsZeroes(bzInt) { + bzStr = append(bzStr, '.') + + // set relevant digits to 0 + for i := 0; i < Precision-inputSize; i++ { + bzStr = append(bzStr, byte('0')) + } + + // set final digits + for len(bzInt) > 0 { + if !IsZeroes(bzInt) { + bzStr = append(bzStr, bzInt[0]) + } + bzInt = bzInt[1:] + } } - // set final digits - copy(bzStr[2+(Precision-inputSize):], bzInt) - } else { - // inputSize + 1 to account for the decimal point that is being added - bzStr = make([]byte, inputSize+1) + bzStr = make([]byte, 0, 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 + bzStr = append(bzStr, bzInt[:decPointPlace]...) // pre-decimal digits + if !IsZeroes(bzInt[decPointPlace:]) { + bzStr = append(bzStr, byte('.')) // decimal point + } + bzInt = bzInt[decPointPlace:] // post-decimal digits + for len(bzInt) > 0 { + if !IsZeroes(bzInt) { + bzStr = append(bzStr, bzInt[0]) + } + bzInt = bzInt[1:] + } } if isNeg { @@ -418,6 +431,16 @@ func (d Dec) String() string { return string(bzStr) } +// IsZeroes checks if the byte array is all zeroes +func IsZeroes(b []byte) bool { + for _, c := range b { + if c != '0' { + return false + } + } + return true +} + // ____ // __| |__ "chop 'em // ` \ round!" diff --git a/numeric/decimal_test.go b/numeric/decimal_test.go index 7b790f20de..40b9e116d0 100644 --- a/numeric/decimal_test.go +++ b/numeric/decimal_test.go @@ -99,14 +99,15 @@ func TestDecString(t *testing.T) { 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"}, + {NewDec(0), "0"}, + {NewDec(1), "1"}, + {NewDec(10), "10"}, + {NewDec(12340), "12340"}, + {NewDecWithPrec(12340, 4), "1.234"}, + {NewDecWithPrec(12340, 5), "0.1234"}, + {NewDecWithPrec(12340, 8), "0.0001234"}, + {NewDecWithPrec(1009009009009009009, 17), "10.09009009009009009"}, + {Dec{Int: nil}, ""}, } for tcIndex, tc := range tests { assert.Equal(t, tc.want, tc.d.String(), "bad String(), index: %v", tcIndex) @@ -297,14 +298,14 @@ func TestDecMarshalJSON(t *testing.T) { want string wantErr bool // if wantErr = false, will also attempt unmarshaling }{ - {"zero", decimal(0), "\"0.000000000000000000\"", false}, + {"zero", decimal(0), "\"0\"", 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}, + {"ten", decimal(10), "\"0.00000000000000001\"", false}, + {"12340", decimal(12340), "\"0.00000000000001234\"", false}, + {"zeroInt", NewDec(0), "\"0\"", false}, + {"oneInt", NewDec(1), "\"1\"", false}, + {"tenInt", NewDec(10), "\"10\"", false}, + {"12340Int", NewDec(12340), "\"12340\"", false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -343,7 +344,7 @@ func TestStringOverflow(t *testing.T) { require.NoError(t, err) dec3 := dec1.Add(dec2) require.Equal(t, - "19844653375691057515930281852116324640.000000000000000000", + "19844653375691057515930281852116324640", dec3.String(), ) } @@ -390,5 +391,26 @@ func TestDiv(t *testing.T) { res := tc.d1.Quo(tc.d2) require.True(t, res.Equal(tc.exp), "unexpected result for test case %d, input: %s %s %s", i, tc.d1, tc.d2, tc.exp) } +} +func TestIsZeroes(t *testing.T) { + tests := []struct { + d []byte + want bool + }{ + {[]byte{}, true}, + {[]byte{'0'}, true}, + {[]byte{'1'}, false}, + {[]byte{'0', '0'}, true}, + {[]byte{'0', '1'}, false}, + {[]byte{'1', '0'}, false}, + {[]byte{'1', '1'}, false}, + {[]byte{'0', '0', '0'}, true}, + {[]byte{'0', '0', '1'}, false}, + } + + for i, tc := range tests { + res := IsZeroes(tc.d) + require.Equal(t, tc.want, res, "unexpected result for test case index %d, expected %v, value %s", i, tc.want, tc.d) + } } diff --git a/shard/shard_state_test.go b/shard/shard_state_test.go index ab3c162443..54a2d9200f 100644 --- a/shard/shard_state_test.go +++ b/shard/shard_state_test.go @@ -23,7 +23,7 @@ var ( const ( json1 = `[{"shard-id":0,"member-count":4,"subcommittee":[{"bls-pubkey":"72616e646f6d206b65792031000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792032000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792033000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792034000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"}]},{"shard-id":1,"member-count":2,"subcommittee":[{"bls-pubkey":"72616e646f6d206b65792035000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792036000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"}]}]` - json2 = `[{"shard-id":0,"member-count":5,"subcommittee":[{"bls-pubkey":"72616e646f6d206b65792031000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792032000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792033000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":"10.000000000000000000","ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792035000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792031000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":"45.123000000000000000","ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"}]},{"shard-id":1,"member-count":4,"subcommittee":[{"bls-pubkey":"72616e646f6d206b65792032000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":"10.000000000000000000","ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792033000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792034000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792035000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":"45.123000000000000000","ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"}]}]` + json2 = `[{"shard-id":0,"member-count":5,"subcommittee":[{"bls-pubkey":"72616e646f6d206b65792031000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792032000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792033000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":"10","ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792035000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792031000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":"45.123","ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"}]},{"shard-id":1,"member-count":4,"subcommittee":[{"bls-pubkey":"72616e646f6d206b65792032000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":"10","ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792033000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792034000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":null,"ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"},{"bls-pubkey":"72616e646f6d206b65792035000000000000000000000000000000000000000000000000000000000000000000000000","effective-stake":"45.123","ecdsa-address":"one1qqqqqqqqqqqqqqqqqqqqqqq423ktdf2pznf238"}]}]` ) func init() {