diff --git a/marshal_OrderPreserve_test.toml b/marshal_OrderPreserve_test.toml index 9d68b599..792b72ed 100644 --- a/marshal_OrderPreserve_test.toml +++ b/marshal_OrderPreserve_test.toml @@ -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 diff --git a/marshal_test.go b/marshal_test.go index 45c0e921..c33e748b 100644 --- a/marshal_test.go +++ b/marshal_test.go @@ -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"` @@ -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, diff --git a/marshal_test.toml b/marshal_test.toml index 1c5f98e7..ba5e110b 100644 --- a/marshal_test.toml +++ b/marshal_test.toml @@ -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 diff --git a/tomltree_write.go b/tomltree_write.go index 9381a88f..ee46773b 100644 --- a/tomltree_write.go +++ b/tomltree_write.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "math" + "math/big" "reflect" "sort" "strconv" @@ -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