Skip to content

Commit

Permalink
Add min exponent width option in double-to-string conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
pengzhenyi2015 committed Aug 1, 2019
1 parent 3f9cd30 commit e4a9385
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 2 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Expand Up @@ -13,3 +13,4 @@ Martin Olsson <mnemo@minimum.se>
Kent Williams <chaircrusher@gmail.com>
Elan Ruusamäe <glen@delfi.ee>
Colin Hirsch <github@colin-hirsch.net>
Zhenyi Peng <zhenyipeng@tencent.com>
3 changes: 3 additions & 0 deletions Changelog
@@ -1,3 +1,6 @@
2019-08-01:
Add min exponent width option in double-to-string conversion.

2019-06-22:
Remove redundant parenthesis.

Expand Down
6 changes: 6 additions & 0 deletions double-conversion/double-to-string.cc
Expand Up @@ -97,6 +97,7 @@ void DoubleToStringConverter::CreateExponentialRepresentation(
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';
Expand All @@ -105,6 +106,11 @@ void DoubleToStringConverter::CreateExponentialRepresentation(
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);
}
Expand Down
10 changes: 8 additions & 2 deletions double-conversion/double-to-string.h
Expand Up @@ -104,14 +104,18 @@ class DoubleToStringConverter {
// 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 exponent width may add up to min_exponent_width by adding prefix '0',
// but the exponent will never have more than 5 digits as kMaxExponentLength is 5
DoubleToStringConverter(int flags,
const char* infinity_symbol,
const char* nan_symbol,
char exponent_character,
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),
Expand All @@ -121,7 +125,8 @@ class DoubleToStringConverter {
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) ||
Expand Down Expand Up @@ -378,6 +383,7 @@ class DoubleToStringConverter {
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);
};
Expand Down
84 changes: 84 additions & 0 deletions test/cctest/test-conversions.cc
Expand Up @@ -71,6 +71,90 @@ TEST(DoubleToShortest) {
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();
Expand Down

0 comments on commit e4a9385

Please sign in to comment.