Commit 33d3277c authored by Tom Jackson's avatar Tom Jackson Committed by Chip Turner

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
parent ba00a0d4
...@@ -649,6 +649,11 @@ class FormatValue<double> { ...@@ -649,6 +649,11 @@ class FormatValue<double> {
break; break;
}; };
auto flags =
DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN |
(arg.trailingDot ? DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT
: 0);
double val = val_; double val = val_;
switch (arg.presentation) { switch (arg.presentation) {
case '%': case '%':
...@@ -660,13 +665,14 @@ class FormatValue<double> { ...@@ -660,13 +665,14 @@ class FormatValue<double> {
DoubleToStringConverter::kMaxFixedDigitsAfterPoint) { DoubleToStringConverter::kMaxFixedDigitsAfterPoint) {
arg.precision = DoubleToStringConverter::kMaxFixedDigitsAfterPoint; arg.precision = DoubleToStringConverter::kMaxFixedDigitsAfterPoint;
} }
DoubleToStringConverter conv( DoubleToStringConverter conv(flags,
DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN, infinitySymbol,
infinitySymbol, nanSymbol,
nanSymbol, exponentSymbol,
exponentSymbol, -4,
-4, arg.precision, arg.precision,
0, 0); 0,
0);
arg.enforce(conv.ToFixed(val, arg.precision, &builder), arg.enforce(conv.ToFixed(val, arg.precision, &builder),
"fixed double conversion failed"); "fixed double conversion failed");
} }
...@@ -678,13 +684,14 @@ class FormatValue<double> { ...@@ -678,13 +684,14 @@ class FormatValue<double> {
arg.precision = DoubleToStringConverter::kMaxExponentialDigits; arg.precision = DoubleToStringConverter::kMaxExponentialDigits;
} }
DoubleToStringConverter conv( DoubleToStringConverter conv(flags,
DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN, infinitySymbol,
infinitySymbol, nanSymbol,
nanSymbol, exponentSymbol,
exponentSymbol, -4,
-4, arg.precision, arg.precision,
0, 0); 0,
0);
arg.enforce(conv.ToExponential(val, arg.precision, &builder)); arg.enforce(conv.ToExponential(val, arg.precision, &builder));
} }
break; break;
...@@ -698,13 +705,14 @@ class FormatValue<double> { ...@@ -698,13 +705,14 @@ class FormatValue<double> {
DoubleToStringConverter::kMaxPrecisionDigits) { DoubleToStringConverter::kMaxPrecisionDigits) {
arg.precision = DoubleToStringConverter::kMaxPrecisionDigits; arg.precision = DoubleToStringConverter::kMaxPrecisionDigits;
} }
DoubleToStringConverter conv( DoubleToStringConverter conv(flags,
DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN, infinitySymbol,
infinitySymbol, nanSymbol,
nanSymbol, exponentSymbol,
exponentSymbol, -4,
-4, arg.precision, arg.precision,
0, 0); 0,
0);
arg.enforce(conv.ToShortest(val, &builder)); arg.enforce(conv.ToShortest(val, &builder));
} }
break; break;
......
...@@ -96,7 +96,15 @@ void FormatArg::initSlow() { ...@@ -96,7 +96,15 @@ void FormatArg::initSlow() {
while (p != end && *p >= '0' && *p <= '9') { while (p != end && *p >= '0' && *p <= '9') {
++p; ++p;
} }
precision = to<int>(StringPiece(b, p)); if (p != b) {
precision = to<int>(StringPiece(b, p));
if (p != end && *p == '.') {
trailingDot = true;
++p;
}
} else {
trailingDot = true;
}
if (p == end) return; if (p == end) return;
} }
......
...@@ -46,6 +46,7 @@ struct FormatArg { ...@@ -46,6 +46,7 @@ struct FormatArg {
sign(Sign::DEFAULT), sign(Sign::DEFAULT),
basePrefix(false), basePrefix(false),
thousandsSeparator(false), thousandsSeparator(false),
trailingDot(false),
width(kDefaultWidth), width(kDefaultWidth),
precision(kDefaultPrecision), precision(kDefaultPrecision),
presentation(kDefaultPresentation), presentation(kDefaultPresentation),
...@@ -128,6 +129,11 @@ struct FormatArg { ...@@ -128,6 +129,11 @@ struct FormatArg {
*/ */
bool thousandsSeparator; bool thousandsSeparator;
/**
* Force a trailing decimal on doubles which could be rendered as ints
*/
bool trailingDot;
/** /**
* Field width * Field width
*/ */
......
...@@ -124,7 +124,7 @@ Format string (`vformat`): ...@@ -124,7 +124,7 @@ Format string (`vformat`):
- `format_spec`: format specification, see below - `format_spec`: format specification, see below
Format specification: 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 - `fill` (may only be specified if `align` is also specified): pad with this
character ('` `' (space) or '`0`' (zero) might be useful; space is default) character ('` `' (space) or '`0`' (zero) might be useful; space is default)
...@@ -149,6 +149,8 @@ Format specification: ...@@ -149,6 +149,8 @@ Format specification:
- for floating point values, number of digits after decimal point ('`f`' or - for floating point values, number of digits after decimal point ('`f`' or
'`F`' presentation) or number of significant digits ('`g`' or '`G`') '`F`' presentation) or number of significant digits ('`g`' or '`G`')
- for others, maximum field size (truncate subsequent characters) - 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 - `type`: presentation format, see below
Presentation formats: Presentation formats:
......
...@@ -239,6 +239,13 @@ TEST(Format, Float) { ...@@ -239,6 +239,13 @@ TEST(Format, Float) {
EXPECT_EQ("0.10", sformat("{:.2f}", 0.1)); EXPECT_EQ("0.10", sformat("{:.2f}", 0.1));
EXPECT_EQ("0.01", sformat("{:.2f}", 0.01)); EXPECT_EQ("0.01", sformat("{:.2f}", 0.01));
EXPECT_EQ("0.00", sformat("{:.2f}", 0.001)); 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) { TEST(Format, MultiLevel) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment