Merge pull request #179 from c9s/util/get-num-of-fractional-digits

feature: get num of fractional parts
This commit is contained in:
YC 2021-03-21 12:55:44 +08:00 committed by GitHub
commit 6858d25070
2 changed files with 87 additions and 24 deletions

View File

@ -167,7 +167,7 @@ var ErrPrecisionLoss = errors.New("precision loss")
func Parse(input string) (num int64, numDecimalPoints int, err error) {
var neg int64 = 1
var digit int64
for i := 0 ; i < len(input) ; i++ {
for i := 0; i < len(input); i++ {
c := input[i]
if c == '-' {
neg = -1
@ -177,15 +177,15 @@ func Parse(input string) (num int64, numDecimalPoints int, err error) {
return
}
num = num * 10 + digit
num = num*10 + digit
} else if c == '.' {
i++
if i > len(input) - 1 {
if i > len(input)-1 {
err = fmt.Errorf("expect fraction numbers after dot")
return
}
for j := i ; j < len(input); j++ {
for j := i; j < len(input); j++ {
fc := input[j]
if fc >= '0' && fc <= '9' {
digit, err = strconv.ParseInt(string(fc), 10, 64)
@ -194,10 +194,10 @@ func Parse(input string) (num int64, numDecimalPoints int, err error) {
}
numDecimalPoints++
num = num * 10 + digit
num = num*10 + digit
if numDecimalPoints >= MaxPrecision {
return num, numDecimalPoints,ErrPrecisionLoss
return num, numDecimalPoints, ErrPrecisionLoss
}
} else {
err = fmt.Errorf("expect digit, got %c", fc)
@ -263,3 +263,15 @@ func Max(a, b Value) Value {
return b
}
func NumFractionalDigits(a Value) int {
numPow := 0
for pow := int64(DefaultPow); pow%10 != 1; pow /= 10 {
numPow++
}
numZeros := 0
for v := a.Int64(); v%10 == 0; v /= 10 {
numZeros++
}
return numPow - numZeros
}

View File

@ -14,40 +14,40 @@ func TestParse(t *testing.T) {
wantErr bool
}{
{
args: args{ input: "-99.9" },
wantNum: -999,
args: args{input: "-99.9"},
wantNum: -999,
wantNumDecimalPoints: 1,
wantErr: false,
wantErr: false,
},
{
args: args{ input: "0.12345678" },
wantNum: 12345678,
args: args{input: "0.12345678"},
wantNum: 12345678,
wantNumDecimalPoints: 8,
wantErr: false,
wantErr: false,
},
{
args: args{ input: "a" },
wantNum: 0,
args: args{input: "a"},
wantNum: 0,
wantNumDecimalPoints: 0,
wantErr: true,
wantErr: true,
},
{
args: args{ input: "0.1" },
wantNum: 1,
args: args{input: "0.1"},
wantNum: 1,
wantNumDecimalPoints: 1,
wantErr: false,
wantErr: false,
},
{
args: args{ input: "100" },
wantNum: 100,
args: args{input: "100"},
wantNum: 100,
wantNumDecimalPoints: 0,
wantErr: false,
wantErr: false,
},
{
args: args{ input: "100.9999" },
wantNum: 1009999,
args: args{input: "100.9999"},
wantNum: 1009999,
wantNumDecimalPoints: 4,
wantErr: false,
wantErr: false,
},
}
for _, tt := range tests {
@ -66,3 +66,54 @@ func TestParse(t *testing.T) {
})
}
}
func TestNumFractionalDigits(t *testing.T) {
tests := []struct {
name string
v Value
want int
}{
{
name: "over the default precision",
v: MustNewFromString("0.123456789"),
want: 8,
},
{
name: "ignore the integer part",
v: MustNewFromString("123.4567"),
want: 4,
},
{
name: "ignore the sign",
v: MustNewFromString("-123.4567"),
want: 4,
},
{
name: "ignore the trailing zero",
v: MustNewFromString("-123.45000000"),
want: 2,
},
{
name: "no fractional parts",
v: MustNewFromString("-1"),
want: 0,
},
{
name: "no fractional parts",
v: MustNewFromString("-1.0"),
want: 0,
},
{
name: "only fractional part",
v: MustNewFromString(".123456"),
want: 6,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := NumFractionalDigits(tt.v); got != tt.want {
t.Errorf("NumFractionalDigits() = %v, want %v", got, tt.want)
}
})
}
}