Add scientific notation parsing

This commit is contained in:
Thiago Arruda 2015-07-24 13:16:41 -03:00
parent 6da60a24bd
commit 849f553b9d
2 changed files with 37 additions and 2 deletions

View file

@ -82,12 +82,23 @@ func New(value int64, exp int32) Decimal {
func NewFromString(value string) (Decimal, error) { func NewFromString(value string) (Decimal, error) {
var intString string var intString string
var exp int32 var exp int32
// Check if number is using scientific notation
eIndex := strings.IndexAny(value, "Ee")
if eIndex != -1 {
expInt, err := strconv.ParseInt(value[eIndex+1:len(value)], 10, 32)
if err != nil {
return Decimal{}, fmt.Errorf("can't convert %s to decimal: exponent is not numeric", value)
}
value = value[0:eIndex]
exp = int32(expInt)
}
parts := strings.Split(value, ".") parts := strings.Split(value, ".")
if len(parts) == 1 { if len(parts) == 1 {
// There is no decimal point, we can just parse the original string as // There is no decimal point, we can just parse the original string as
// an int // an int
intString = value intString = value
exp = 0
} else if len(parts) == 2 { } else if len(parts) == 2 {
intString = parts[0] + parts[1] intString = parts[0] + parts[1]
expInt := -len(parts[1]) expInt := -len(parts[1])
@ -95,7 +106,7 @@ func NewFromString(value string) (Decimal, error) {
// NOTE(vadim): I doubt a string could realistically be this long // NOTE(vadim): I doubt a string could realistically be this long
return Decimal{}, fmt.Errorf("can't convert %s to decimal: fractional part too long", value) return Decimal{}, fmt.Errorf("can't convert %s to decimal: fractional part too long", value)
} }
exp = int32(expInt) exp += int32(expInt)
} else { } else {
return Decimal{}, fmt.Errorf("can't convert %s to decimal: too many .s", value) return Decimal{}, fmt.Errorf("can't convert %s to decimal: too many .s", value)
} }

View file

@ -32,6 +32,16 @@ var testTable = map[float64]string{
.1000000000000008: "0.1000000000000008", .1000000000000008: "0.1000000000000008",
} }
var testTableScientificNotation = map[string]string{
"1e9": "1000000000",
"2.41E-3": "0.00241",
"24.2E-4": "0.00242",
"243E-5": "0.00243",
"-1e-5": "-0.00001",
"-245E3": "-245000",
"1.2345E-1": "0.12345",
}
func init() { func init() {
// add negatives // add negatives
for f, s := range testTable { for f, s := range testTable {
@ -76,6 +86,17 @@ func TestNewFromString(t *testing.T) {
d.value.String(), d.exp) d.value.String(), d.exp)
} }
} }
for e, s := range testTableScientificNotation {
d, err := NewFromString(e)
if err != nil {
t.Errorf("error while parsing %s", e)
} else if d.String() != s {
t.Errorf("expected %s, got %s (%s, %d)",
s, d.String(),
d.value.String(), d.exp)
}
}
} }
func TestNewFromStringErrs(t *testing.T) { func TestNewFromStringErrs(t *testing.T) {
@ -95,6 +116,9 @@ func TestNewFromStringErrs(t *testing.T) {
".5.2", ".5.2",
"8..2", "8..2",
"8.1.", "8.1.",
"1e",
"1-e",
"1e9e",
} }
for _, s := range tests { for _, s := range tests {