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) {
|
||||
var intString string
|
||||
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, ".")
|
||||
if len(parts) == 1 {
|
||||
// There is no decimal point, we can just parse the original string as
|
||||
// an int
|
||||
intString = value
|
||||
exp = 0
|
||||
} else if len(parts) == 2 {
|
||||
intString = parts[0] + 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
|
||||
return Decimal{}, fmt.Errorf("can't convert %s to decimal: fractional part too long", value)
|
||||
}
|
||||
exp = int32(expInt)
|
||||
exp += int32(expInt)
|
||||
} else {
|
||||
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",
|
||||
}
|
||||
|
||||
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() {
|
||||
// add negatives
|
||||
for f, s := range testTable {
|
||||
|
@ -76,6 +86,17 @@ func TestNewFromString(t *testing.T) {
|
|||
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) {
|
||||
|
@ -95,6 +116,9 @@ func TestNewFromStringErrs(t *testing.T) {
|
|||
".5.2",
|
||||
"8..2",
|
||||
"8.1.",
|
||||
"1e",
|
||||
"1-e",
|
||||
"1e9e",
|
||||
}
|
||||
|
||||
for _, s := range tests {
|
||||
|
|
Loading…
Reference in a new issue