From: Tom Jackson Date: Thu, 24 Jul 2014 00:19:47 +0000 (-0700) Subject: Support trailing decimals for floats X-Git-Tag: v0.22.0~435 X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=33d3277c2e936568c1d271eeaddd44ce461e6858;p=folly.git Support trailing decimals for floats Summary: So integer-like numbers can be formatted in a manner which disambiguates them from integers. Test Plan: Unit tests Reviewed By: tudorb@fb.com Subscribers: jfh, cscheau FB internal diff: D1454446 --- diff --git a/folly/Format-inl.h b/folly/Format-inl.h index 77248b79..f9de1200 100644 --- a/folly/Format-inl.h +++ b/folly/Format-inl.h @@ -649,6 +649,11 @@ class FormatValue { break; }; + auto flags = + DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN | + (arg.trailingDot ? DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT + : 0); + double val = val_; switch (arg.presentation) { case '%': @@ -660,13 +665,14 @@ class FormatValue { DoubleToStringConverter::kMaxFixedDigitsAfterPoint) { arg.precision = DoubleToStringConverter::kMaxFixedDigitsAfterPoint; } - DoubleToStringConverter conv( - DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN, - infinitySymbol, - nanSymbol, - exponentSymbol, - -4, arg.precision, - 0, 0); + DoubleToStringConverter conv(flags, + infinitySymbol, + nanSymbol, + exponentSymbol, + -4, + arg.precision, + 0, + 0); arg.enforce(conv.ToFixed(val, arg.precision, &builder), "fixed double conversion failed"); } @@ -678,13 +684,14 @@ class FormatValue { arg.precision = DoubleToStringConverter::kMaxExponentialDigits; } - DoubleToStringConverter conv( - DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN, - infinitySymbol, - nanSymbol, - exponentSymbol, - -4, arg.precision, - 0, 0); + DoubleToStringConverter conv(flags, + infinitySymbol, + nanSymbol, + exponentSymbol, + -4, + arg.precision, + 0, + 0); arg.enforce(conv.ToExponential(val, arg.precision, &builder)); } break; @@ -698,13 +705,14 @@ class FormatValue { DoubleToStringConverter::kMaxPrecisionDigits) { arg.precision = DoubleToStringConverter::kMaxPrecisionDigits; } - DoubleToStringConverter conv( - DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN, - infinitySymbol, - nanSymbol, - exponentSymbol, - -4, arg.precision, - 0, 0); + DoubleToStringConverter conv(flags, + infinitySymbol, + nanSymbol, + exponentSymbol, + -4, + arg.precision, + 0, + 0); arg.enforce(conv.ToShortest(val, &builder)); } break; diff --git a/folly/Format.cpp b/folly/Format.cpp index 53a21862..feec8fb2 100644 --- a/folly/Format.cpp +++ b/folly/Format.cpp @@ -96,7 +96,15 @@ void FormatArg::initSlow() { while (p != end && *p >= '0' && *p <= '9') { ++p; } - precision = to(StringPiece(b, p)); + if (p != b) { + precision = to(StringPiece(b, p)); + if (p != end && *p == '.') { + trailingDot = true; + ++p; + } + } else { + trailingDot = true; + } if (p == end) return; } diff --git a/folly/FormatArg.h b/folly/FormatArg.h index e8150646..b6a00187 100644 --- a/folly/FormatArg.h +++ b/folly/FormatArg.h @@ -46,6 +46,7 @@ struct FormatArg { sign(Sign::DEFAULT), basePrefix(false), thousandsSeparator(false), + trailingDot(false), width(kDefaultWidth), precision(kDefaultPrecision), presentation(kDefaultPresentation), @@ -128,6 +129,11 @@ struct FormatArg { */ bool thousandsSeparator; + /** + * Force a trailing decimal on doubles which could be rendered as ints + */ + bool trailingDot; + /** * Field width */ diff --git a/folly/docs/Format.md b/folly/docs/Format.md index 5696c8be..012f0a28 100644 --- a/folly/docs/Format.md +++ b/folly/docs/Format.md @@ -124,7 +124,7 @@ Format string (`vformat`): - `format_spec`: format specification, see below Format specification: -`[[fill] align] [sign] ["#"] ["0"] [width] [","] ["." precision] [type]` +`[[fill] align] [sign] ["#"] ["0"] [width] [","] ["." precision] ["."] [type]` - `fill` (may only be specified if `align` is also specified): pad with this character ('` `' (space) or '`0`' (zero) might be useful; space is default) @@ -149,6 +149,8 @@ Format specification: - for floating point values, number of digits after decimal point ('`f`' or '`F`' presentation) or number of significant digits ('`g`' or '`G`') - for others, maximum field size (truncate subsequent characters) +- '`.`' (when used after precision or in lieu of precison): Forces a trailing + decimal point to make it clear this is a floating point value. - `type`: presentation format, see below Presentation formats: diff --git a/folly/test/FormatTest.cpp b/folly/test/FormatTest.cpp index 8db3f09d..44873273 100644 --- a/folly/test/FormatTest.cpp +++ b/folly/test/FormatTest.cpp @@ -239,6 +239,13 @@ TEST(Format, Float) { EXPECT_EQ("0.10", sformat("{:.2f}", 0.1)); EXPECT_EQ("0.01", sformat("{:.2f}", 0.01)); EXPECT_EQ("0.00", sformat("{:.2f}", 0.001)); + + EXPECT_EQ("100000.", sformat("{:.}", 100000.0)); + EXPECT_EQ("1e+6", sformat("{:.}", 1000000.0)); + EXPECT_EQ(" 100000.", sformat("{:8.}", 100000.0)); + EXPECT_EQ("100000.", sformat("{:4.}", 100000.0)); + EXPECT_EQ(" 100000", sformat("{:8.8}", 100000.0)); + EXPECT_EQ(" 100000.", sformat("{:8.8.}", 100000.0)); } TEST(Format, MultiLevel) {