diff --git a/pkg/fixedpoint/convert_test.go b/pkg/fixedpoint/convert_test.go index 866c89b52..a992c0f79 100644 --- a/pkg/fixedpoint/convert_test.go +++ b/pkg/fixedpoint/convert_test.go @@ -1,66 +1,124 @@ package fixedpoint import ( + "fmt" "testing" "github.com/stretchr/testify/assert" ) func Test_FormatString(t *testing.T) { - assert := assert.New(t) + cases := []struct { + input string + prec int + expected string + }{ + {input: "0.57", prec: 5, expected: "0.57000"}, + {input: "-0.57", prec: 5, expected: "-0.57000"}, + {input: "0.57123456", prec: 8, expected: "0.57123456"}, + {input: "-0.57123456", prec: 8, expected: "-0.57123456"}, + {input: "0.57123456", prec: 5, expected: "0.57123"}, + {input: "-0.57123456", prec: 5, expected: "-0.57123"}, + {input: "0.57123456", prec: 0, expected: "0"}, + {input: "-0.57123456", prec: 0, expected: "0"}, + {input: "0.57123456", prec: -1, expected: "0"}, + {input: "-0.57123456", prec: -1, expected: "0"}, + {input: "0.57123456", prec: -5, expected: "0"}, + {input: "-0.57123456", prec: -5, expected: "0"}, + {input: "0.57123456", prec: -9, expected: "0"}, + {input: "-0.57123456", prec: -9, expected: "0"}, - t.Run("0.57 with prec = 5, expected 0.57", func(t *testing.T) { - v := MustNewFromString("0.57") - s := v.FormatString(5) - assert.Equal("0.57000", s) - }) + {input: "1.23456789", prec: 9, expected: "1.234567890"}, + {input: "-1.23456789", prec: 9, expected: "-1.234567890"}, + {input: "1.02345678", prec: 9, expected: "1.023456780"}, + {input: "-1.02345678", prec: 9, expected: "-1.023456780"}, + {input: "1.02345678", prec: 2, expected: "1.02"}, + {input: "-1.02345678", prec: 2, expected: "-1.02"}, + {input: "1.02345678", prec: 0, expected: "1"}, + {input: "-1.02345678", prec: 0, expected: "-1"}, + {input: "1.02345678", prec: -1, expected: "0"}, + {input: "-1.02345678", prec: -1, expected: "0"}, + {input: "1.02345678", prec: -10, expected: "0"}, + {input: "-1.02345678", prec: -10, expected: "0"}, - t.Run("0.57123456 with prec = 5, expected 0.57123", func(t *testing.T) { - v := MustNewFromString("0.57123456") - s := v.FormatString(5) - assert.Equal("0.57123", s) - }) + {input: "0.0001234", prec: 9, expected: "0.000123400"}, + {input: "-0.0001234", prec: 9, expected: "-0.000123400"}, + {input: "0.0001234", prec: 7, expected: "0.0001234"}, + {input: "-0.0001234", prec: 7, expected: "-0.0001234"}, + {input: "0.0001234", prec: 5, expected: "0.00012"}, + {input: "-0.0001234", prec: 5, expected: "-0.00012"}, + {input: "0.0001234", prec: 3, expected: "0.000"}, + {input: "-0.0001234", prec: 3, expected: "0.000"}, + {input: "0.0001234", prec: 2, expected: "0.00"}, + {input: "-0.0001234", prec: 2, expected: "0.00"}, + {input: "0.0001234", prec: 0, expected: "0"}, + {input: "-0.0001234", prec: 0, expected: "0"}, + {input: "0.00001234", prec: -1, expected: "0"}, + {input: "-0.00001234", prec: -1, expected: "0"}, + {input: "0.00001234", prec: -5, expected: "0"}, + {input: "-0.00001234", prec: -5, expected: "0"}, + {input: "0.00001234", prec: -9, expected: "0"}, + {input: "-0.00001234", prec: -9, expected: "0"}, - t.Run("1.23456789 with prec = 9, expected 1.23456789", func(t *testing.T) { - v := MustNewFromString("1.23456789") - s := v.FormatString(9) - assert.Equal("1.234567890", s) - }) + {input: "12.3456789", prec: 10, expected: "12.3456789000"}, + {input: "-12.3456789", prec: 10, expected: "-12.3456789000"}, + {input: "12.3456789", prec: 9, expected: "12.345678900"}, + {input: "-12.3456789", prec: 9, expected: "-12.345678900"}, + {input: "12.3456789", prec: 7, expected: "12.3456789"}, + {input: "-12.3456789", prec: 7, expected: "-12.3456789"}, + {input: "12.3456789", prec: 5, expected: "12.34567"}, + {input: "-12.3456789", prec: 5, expected: "-12.34567"}, + {input: "12.3456789", prec: 1, expected: "12.3"}, + {input: "-12.3456789", prec: 1, expected: "-12.3"}, + {input: "12.3456789", prec: 0, expected: "12"}, + {input: "-12.3456789", prec: 0, expected: "-12"}, + {input: "12.3456789", prec: -1, expected: "10"}, + {input: "-12.3456789", prec: -1, expected: "-10"}, + {input: "12.3456789", prec: -2, expected: "0"}, + {input: "-12.3456789", prec: -2, expected: "0"}, + {input: "12.3456789", prec: -3, expected: "0"}, + {input: "-12.3456789", prec: -3, expected: "0"}, - t.Run("1.02345678 with prec = 9, expected 1.02345678", func(t *testing.T) { - v := MustNewFromString("1.02345678") - s := v.FormatString(9) - assert.Equal("1.023456780", s) - }) + {input: "12345678.9", prec: 10, expected: "12345678.9000000000"}, + {input: "-12345678.9", prec: 10, expected: "-12345678.9000000000"}, + {input: "12345678.9", prec: 3, expected: "12345678.900"}, + {input: "-12345678.9", prec: 3, expected: "-12345678.900"}, + {input: "12345678.9", prec: 1, expected: "12345678.9"}, + {input: "-12345678.9", prec: 1, expected: "-12345678.9"}, + {input: "12345678.9", prec: 0, expected: "12345678"}, + {input: "-12345678.9", prec: 0, expected: "-12345678"}, + {input: "12345678.9", prec: -2, expected: "12345600"}, + {input: "-12345678.9", prec: -2, expected: "-12345600"}, + {input: "12345678.9", prec: -5, expected: "12300000"}, + {input: "-12345678.9", prec: -5, expected: "-12300000"}, + {input: "12345678.9", prec: -7, expected: "10000000"}, + {input: "-12345678.9", prec: -7, expected: "-10000000"}, + {input: "12345678.9", prec: -8, expected: "0"}, + {input: "-12345678.9", prec: -8, expected: "0"}, + {input: "12345678.9", prec: -10, expected: "0"}, + {input: "-12345678.9", prec: -10, expected: "0"}, - t.Run("-0.57 with prec = 5, expected -0.57", func(t *testing.T) { - v := MustNewFromString("-0.57") - s := v.FormatString(5) - assert.Equal("-0.57000", s) - }) + {input: "123000", prec: 7, expected: "123000.0000000"}, + {input: "-123000", prec: 7, expected: "-123000.0000000"}, + {input: "123000", prec: 2, expected: "123000.00"}, + {input: "-123000", prec: 2, expected: "-123000.00"}, + {input: "123000", prec: 0, expected: "123000"}, + {input: "-123000", prec: 0, expected: "-123000"}, + {input: "123000", prec: -1, expected: "123000"}, + {input: "-123000", prec: -1, expected: "-123000"}, + {input: "123000", prec: -5, expected: "100000"}, + {input: "-123000", prec: -5, expected: "-100000"}, + {input: "123000", prec: -6, expected: "0"}, + {input: "-123000", prec: -6, expected: "0"}, + {input: "123000", prec: -8, expected: "0"}, + {input: "-123000", prec: -8, expected: "0"}, + } - t.Run("-1.23456789 with prec = 9, expected 1.23456789", func(t *testing.T) { - v := MustNewFromString("-1.23456789") - s := v.FormatString(9) - assert.Equal("-1.234567890", s) - }) - - t.Run("-0.00001234 with prec = 3, expected = 0.000", func(t *testing.T) { - v := MustNewFromString("-0.0001234") - s := v.FormatString(3) - assert.Equal("0.000", s) - }) - - // comment out negative precision for dnum testing - t.Run("12.3456789 with prec = -1, expected 10", func(t *testing.T) { - v := MustNewFromString("12.3456789") - s := v.FormatString(-1) - assert.Equal("10", s) - }) - - t.Run("12.3456789 with prec = -3, expected = 0", func(t *testing.T) { - v := MustNewFromString("12.3456789") - s := v.FormatString(-2) - assert.Equal("0", s) - }) -} + for _, c := range cases { + t.Run(fmt.Sprintf("%s with prec = %d, expected %s", c.input, c.prec, c.expected), func(t *testing.T) { + v := MustNewFromString(c.input) + s := v.FormatString(c.prec) + assert.Equal(t, c.expected, s) + }) + } +} \ No newline at end of file diff --git a/pkg/fixedpoint/dec.go b/pkg/fixedpoint/dec.go index 85aad5d68..41318f76d 100644 --- a/pkg/fixedpoint/dec.go +++ b/pkg/fixedpoint/dec.go @@ -270,25 +270,46 @@ func (dn Value) FormatString(prec int) string { nd := len(digits) e := int(dn.exp) - nd if -maxLeadingZeros <= dn.exp && dn.exp <= 0 { + if prec < 0 { + return "0" + } // decimal to the left if prec+e+nd > 0 { return sign + "0." + strings.Repeat("0", -e-nd) + digits[:min(prec+e+nd, nd)] + strings.Repeat("0", max(0, prec-nd+e+nd)) - } else if -e-nd > 0 { - return "0." + strings.Repeat("0", -e-nd) + } else if -e-nd > 0 && prec != 0 { + return "0." + strings.Repeat("0", min(prec, -e-nd)) } else { return "0" } } else if -nd < e && e <= -1 { // decimal within dec := nd + e - decimals := digits[dec:min(dec+prec, nd)] - return sign + digits[:dec] + "." + decimals + strings.Repeat("0", max(0, prec-len(decimals))) + if prec > 0 { + decimals := digits[dec:min(dec+prec, nd)] + return sign + digits[:dec] + "." + decimals + strings.Repeat("0", max(0, prec-len(decimals))) + } else if prec == 0 { + return sign + digits[:dec] + } + + sigFigures := digits[0:max(dec+prec, 0)] + if len(sigFigures) == 0 { + return "0" + } + + return sign + sigFigures + strings.Repeat("0", max(-prec, 0)) + } else if 0 < dn.exp && dn.exp <= digitsMax { // decimal to the right if prec > 0 { return sign + digits + strings.Repeat("0", e) + "." + strings.Repeat("0", prec) - } else { + } else if prec+e >= 0 { return sign + digits + strings.Repeat("0", e) + } else { + if len(digits) <= -prec-e { + return "0" + } + + return sign + digits[0:len(digits)+prec+e] + strings.Repeat("0", -prec) } } else { // scientific notation