Add min exponent width option in double-to-string conversion (#116)
diff --git a/AUTHORS b/AUTHORS
index 3fcb1f7..4edeeed 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -13,3 +13,4 @@
Kent Williams <chaircrusher@gmail.com>
Elan Ruusamäe <glen@delfi.ee>
Colin Hirsch <github@colin-hirsch.net>
+Zhenyi Peng <zhenyipeng@tencent.com>
diff --git a/Changelog b/Changelog
index a09940d..12b8a51 100644
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,6 @@
+2019-08-01:
+ Add min exponent width option in double-to-string conversion.
+
2019-06-22:
Remove redundant parenthesis.
diff --git a/double-conversion/double-to-string.cc b/double-conversion/double-to-string.cc
index 13c7110..4562f99 100644
--- a/double-conversion/double-to-string.cc
+++ b/double-conversion/double-to-string.cc
@@ -97,6 +97,7 @@
return;
}
DOUBLE_CONVERSION_ASSERT(exponent < 1e4);
+ // Changing this constant requires updating the comment of DoubleToStringConverter constructor
const int kMaxExponentLength = 5;
char buffer[kMaxExponentLength + 1];
buffer[kMaxExponentLength] = '\0';
@@ -105,6 +106,11 @@
buffer[--first_char_pos] = '0' + (exponent % 10);
exponent /= 10;
}
+ // Add prefix '0' to make exponent width >= min(min_exponent_with_, kMaxExponentLength)
+ // For example: convert 1e+9 -> 1e+09, if min_exponent_with_ is set to 2
+ while(kMaxExponentLength - first_char_pos < std::min(min_exponent_width_, kMaxExponentLength)) {
+ buffer[--first_char_pos] = '0';
+ }
result_builder->AddSubstring(&buffer[first_char_pos],
kMaxExponentLength - first_char_pos);
}
diff --git a/double-conversion/double-to-string.h b/double-conversion/double-to-string.h
index c1be34d..a44fa3c 100644
--- a/double-conversion/double-to-string.h
+++ b/double-conversion/double-to-string.h
@@ -104,6 +104,12 @@
// ToPrecision(230.0, 2) -> "230"
// ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT.
// ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT.
+ //
+ // The min_exponent_width is used for exponential representations.
+ // The converter adds leading '0's to the exponent until the exponent
+ // is at least min_exponent_width digits long.
+ // The min_exponent_width is clamped to 5.
+ // As such, the exponent may never have more than 5 digits in total.
DoubleToStringConverter(int flags,
const char* infinity_symbol,
const char* nan_symbol,
@@ -111,7 +117,8 @@
int decimal_in_shortest_low,
int decimal_in_shortest_high,
int max_leading_padding_zeroes_in_precision_mode,
- int max_trailing_padding_zeroes_in_precision_mode)
+ int max_trailing_padding_zeroes_in_precision_mode,
+ int min_exponent_width = 0)
: flags_(flags),
infinity_symbol_(infinity_symbol),
nan_symbol_(nan_symbol),
@@ -121,7 +128,8 @@
max_leading_padding_zeroes_in_precision_mode_(
max_leading_padding_zeroes_in_precision_mode),
max_trailing_padding_zeroes_in_precision_mode_(
- max_trailing_padding_zeroes_in_precision_mode) {
+ max_trailing_padding_zeroes_in_precision_mode),
+ min_exponent_width_(min_exponent_width) {
// When 'trailing zero after the point' is set, then 'trailing point'
// must be set too.
DOUBLE_CONVERSION_ASSERT(((flags & EMIT_TRAILING_DECIMAL_POINT) != 0) ||
@@ -378,6 +386,7 @@
const int decimal_in_shortest_high_;
const int max_leading_padding_zeroes_in_precision_mode_;
const int max_trailing_padding_zeroes_in_precision_mode_;
+ const int min_exponent_width_;
DOUBLE_CONVERSION_DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter);
};
diff --git a/test/cctest/test-conversions.cc b/test/cctest/test-conversions.cc
index 397d8b3..e723c95 100644
--- a/test/cctest/test-conversions.cc
+++ b/test/cctest/test-conversions.cc
@@ -71,6 +71,90 @@
CHECK(dc.ToShortest(-0.0, &builder));
CHECK_EQ("0", builder.Finalize());
+ // Test min_exponent_width
+ flags = DoubleToStringConverter::UNIQUE_ZERO |
+ DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN;
+ DoubleToStringConverter dcExpWidth2(flags, NULL, NULL, 'e', -4, 6, 0, 0, 2);
+
+ builder.Reset();
+ CHECK(dcExpWidth2.ToShortest(11111111111.0, &builder));
+ CHECK_EQ("1.1111111111e+10", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dcExpWidth2.ToShortest(1111111111.0, &builder));
+ CHECK_EQ("1.111111111e+09", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dcExpWidth2.ToShortest(1111111.0, &builder));
+ CHECK_EQ("1.111111e+06", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dcExpWidth2.ToShortest(111111.0, &builder));
+ CHECK_EQ("111111", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dcExpWidth2.ToShortest(10000000000.0, &builder));
+ CHECK_EQ("1e+10", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dcExpWidth2.ToShortest(1000000000.0, &builder));
+ CHECK_EQ("1e+09", builder.Finalize());
+
+ DoubleToStringConverter dcExpWidth0(flags, NULL, NULL, 'e', -4, 6, 0, 0, 0);
+
+ builder.Reset();
+ CHECK(dcExpWidth0.ToShortest(11111111111.0, &builder));
+ CHECK_EQ("1.1111111111e+10", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dcExpWidth0.ToShortest(1111111111.0, &builder));
+ CHECK_EQ("1.111111111e+9", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dcExpWidth0.ToShortest(1111111.0, &builder));
+ CHECK_EQ("1.111111e+6", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dcExpWidth0.ToShortest(111111.0, &builder));
+ CHECK_EQ("111111", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dcExpWidth0.ToShortest(10000000000.0, &builder));
+ CHECK_EQ("1e+10", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dcExpWidth0.ToShortest(1000000000.0, &builder));
+ CHECK_EQ("1e+9", builder.Finalize());
+
+ // Set min_exponent_width to 100 is equal to 5,
+ // as kMaxExponentLength is defined to 5 in double-to-string.cc
+ DoubleToStringConverter dcExpWidth100(flags, NULL, NULL, 'e', -4, 6, 0, 0, 100);
+
+ builder.Reset();
+ CHECK(dcExpWidth100.ToShortest(11111111111.0, &builder));
+ CHECK_EQ("1.1111111111e+00010", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dcExpWidth100.ToShortest(1111111111.0, &builder));
+ CHECK_EQ("1.111111111e+00009", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dcExpWidth100.ToShortest(1111111.0, &builder));
+ CHECK_EQ("1.111111e+00006", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dcExpWidth100.ToShortest(111111.0, &builder));
+ CHECK_EQ("111111", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dcExpWidth100.ToShortest(10000000000.0, &builder));
+ CHECK_EQ("1e+00010", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dcExpWidth100.ToShortest(1000000000.0, &builder));
+ CHECK_EQ("1e+00009", builder.Finalize());
+ // End of min_exponent_width testing
+
flags = DoubleToStringConverter::NO_FLAGS;
DoubleToStringConverter dc2(flags, NULL, NULL, 'e', -1, 1, 0, 0);
builder.Reset();