@@ -71,6 +71,13 @@ var MarshalJSONWithoutQuotes = false
71
71
// Setting this value to false can be useful for APIs where exact decimal string representation matters.
72
72
var TrimTrailingZeros = true
73
73
74
+ // AvoidScientificNotation specifies whether scientific notation should be used when decimal is turned
75
+ // into a string that has a "negative" precision.
76
+ //
77
+ // For example, 1200 rounded to the nearest 100 cannot accurately be shown as "1200" because the last two
78
+ // digits are unknown. With this set to false, that number would be expressed as "1.2E3" instead.
79
+ var AvoidScientificNotation = true
80
+
74
81
// ExpMaxIterations specifies the maximum number of iterations needed to calculate
75
82
// precise natural exponent value using ExpHullAbrham method.
76
83
var ExpMaxIterations = 1000
@@ -1475,7 +1482,7 @@ func (d Decimal) InexactFloat64() float64 {
1475
1482
//
1476
1483
// -12.345
1477
1484
func (d Decimal ) String () string {
1478
- return d .string (TrimTrailingZeros )
1485
+ return d .string (TrimTrailingZeros , AvoidScientificNotation )
1479
1486
}
1480
1487
1481
1488
// StringFixed returns a rounded fixed-point string with places digits after
@@ -1489,10 +1496,10 @@ func (d Decimal) String() string {
1489
1496
// NewFromFloat(5.45).StringFixed(1) // output: "5.5"
1490
1497
// NewFromFloat(5.45).StringFixed(2) // output: "5.45"
1491
1498
// NewFromFloat(5.45).StringFixed(3) // output: "5.450"
1492
- // NewFromFloat(545).StringFixed(-1) // output: "550 "
1499
+ // NewFromFloat(545).StringFixed(-1) // output: "540 "
1493
1500
func (d Decimal ) StringFixed (places int32 ) string {
1494
1501
rounded := d .Round (places )
1495
- return rounded .string (false )
1502
+ return rounded .string (false , true )
1496
1503
}
1497
1504
1498
1505
// StringFixedBank returns a banker rounded fixed-point string with places digits
@@ -1509,14 +1516,14 @@ func (d Decimal) StringFixed(places int32) string {
1509
1516
// NewFromFloat(545).StringFixedBank(-1) // output: "540"
1510
1517
func (d Decimal ) StringFixedBank (places int32 ) string {
1511
1518
rounded := d .RoundBank (places )
1512
- return rounded .string (false )
1519
+ return rounded .string (false , true )
1513
1520
}
1514
1521
1515
1522
// StringFixedCash returns a Swedish/Cash rounded fixed-point string. For
1516
1523
// more details see the documentation at function RoundCash.
1517
1524
func (d Decimal ) StringFixedCash (interval uint8 ) string {
1518
1525
rounded := d .RoundCash (interval )
1519
- return rounded .string (false )
1526
+ return rounded .string (false , true )
1520
1527
}
1521
1528
1522
1529
// Round rounds the decimal to places decimal places.
@@ -1911,10 +1918,17 @@ func (d Decimal) StringScaled(exp int32) string {
1911
1918
return d .rescale (exp ).String ()
1912
1919
}
1913
1920
1914
- func (d Decimal ) string (trimTrailingZeros bool ) string {
1915
- if d .exp > = 0 {
1921
+ func (d Decimal ) string (trimTrailingZeros , avoidScientificNotation bool ) string {
1922
+ if d .exp = = 0 {
1916
1923
return d .rescale (0 ).value .String ()
1917
1924
}
1925
+ if d .exp >= 0 {
1926
+ if avoidScientificNotation {
1927
+ return d .rescale (0 ).value .String ()
1928
+ } else {
1929
+ return d .ScientificNotationString ()
1930
+ }
1931
+ }
1918
1932
1919
1933
abs := new (big.Int ).Abs (d .value )
1920
1934
str := abs .String ()
@@ -1956,6 +1970,31 @@ func (d Decimal) string(trimTrailingZeros bool) string {
1956
1970
return number
1957
1971
}
1958
1972
1973
+ // ScientificNotationString serializes the decimal into standard scientific notation.
1974
+ //
1975
+ // The notation is normalized to have one non-zero digit followed by a decimal point and
1976
+ // the remaining significant digits followed by "E" and the base-10 exponent.
1977
+ //
1978
+ // A zero, which has no significant digits, is simply serialized to "0".
1979
+ func (d Decimal ) ScientificNotationString () string {
1980
+ exp := int (d .exp )
1981
+ intStr := new (big.Int ).Abs (d .value ).String ()
1982
+ if intStr == "0" {
1983
+ return intStr
1984
+ }
1985
+ first := intStr [0 ]
1986
+ var remaining string
1987
+ if len (intStr ) > 1 {
1988
+ remaining = "." + intStr [1 :]
1989
+ exp = exp + len (intStr ) - 1
1990
+ }
1991
+ number := string (first ) + remaining + "E" + strconv .Itoa (exp )
1992
+ if d .value .Sign () < 0 {
1993
+ return "-" + number
1994
+ }
1995
+ return number
1996
+ }
1997
+
1959
1998
func (d * Decimal ) ensureInitialized () {
1960
1999
if d .value == nil {
1961
2000
d .value = new (big.Int )
0 commit comments