Skip to content

Commit

Permalink
Fix float64 truncation error (#293)
Browse files Browse the repository at this point in the history
Don't truncate float64 representation on marashaling.

Fixes #289
  • Loading branch information
ProfessorMc authored and pelletier committed Aug 27, 2019
1 parent 781fbae commit 3ded2e0
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 6 deletions.
1 change: 1 addition & 0 deletions marshal_OrderPreserve_test.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ title = "TOML Marshal Testing"
uint = 5001
bool = true
float = 123.4
float64 = 123.456782132399
int = 5000
string = "Bite me"
date = 1979-05-27T07:32:00Z
Expand Down
6 changes: 4 additions & 2 deletions marshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ type testMapDoc struct {
type testDocBasics struct {
Uint uint `toml:"uint"`
Bool bool `toml:"bool"`
Float float32 `toml:"float"`
Float32 float32 `toml:"float"`
Float64 float64 `toml:"float64"`
Int int `toml:"int"`
String *string `toml:"string"`
Date time.Time `toml:"date"`
Expand Down Expand Up @@ -174,7 +175,8 @@ var docData = testDoc{
Basics: testDocBasics{
Bool: true,
Date: time.Date(1979, 5, 27, 7, 32, 0, 0, time.UTC),
Float: 123.4,
Float32: 123.4,
Float64: 123.456782132399,
Int: 5000,
Uint: 5001,
String: &biteMe,
Expand Down
1 change: 1 addition & 0 deletions marshal_test.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ title = "TOML Marshal Testing"
bool = true
date = 1979-05-27T07:32:00Z
float = 123.4
float64 = 123.456782132399
int = 5000
string = "Bite me"
uint = 5001
Expand Down
17 changes: 13 additions & 4 deletions tomltree_write.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"io"
"math"
"math/big"
"reflect"
"sort"
"strconv"
Expand Down Expand Up @@ -106,12 +107,20 @@ func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElemen
case int64:
return strconv.FormatInt(value, 10), nil
case float64:
// Ensure a round float does contain a decimal point. Otherwise feeding
// the output back to the parser would convert to an integer.
// Default bit length is full 64
bits := 64
// Float panics if nan is used
if !math.IsNaN(value) {
// if 32 bit accuracy is enough to exactly show, use 32
_, acc := big.NewFloat(value).Float32()
if acc == big.Exact {
bits = 32
}
}
if math.Trunc(value) == value {
return strings.ToLower(strconv.FormatFloat(value, 'f', 1, 32)), nil
return strings.ToLower(strconv.FormatFloat(value, 'f', 1, bits)), nil
}
return strings.ToLower(strconv.FormatFloat(value, 'f', -1, 32)), nil
return strings.ToLower(strconv.FormatFloat(value, 'f', -1, bits)), nil
case string:
if tv.multiline {
return "\"\"\"\n" + encodeMultilineTomlString(value) + "\"\"\"", nil
Expand Down

0 comments on commit 3ded2e0

Please sign in to comment.