mirror of
https://github.com/shopspring/decimal.git
synced 2024-11-22 20:40:48 +01:00
Add scientific notation parsing
This commit is contained in:
parent
6da60a24bd
commit
849f553b9d
2 changed files with 37 additions and 2 deletions
15
decimal.go
15
decimal.go
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue