Chromium Code Reviews| Index: base/strings/string_number_conversions_unittest.cc |
| diff --git a/base/strings/string_number_conversions_unittest.cc b/base/strings/string_number_conversions_unittest.cc |
| index 0cc71a696b443eaedebfae72750edb1152cd4d2d..53f1ce1bab91bd05b27ab6ee2cbc1139dbe2dd31 100644 |
| --- a/base/strings/string_number_conversions_unittest.cc |
| +++ b/base/strings/string_number_conversions_unittest.cc |
| @@ -805,4 +805,234 @@ TEST(StringNumberConversionsTest, HexEncode) { |
| EXPECT_EQ(hex.compare("01FF02FE038081"), 0); |
| } |
| +// http://www.exploringbinary.com/converting-floating-point-numbers-to-binary-strings-in-c/ |
|
Nico
2016/06/08 00:45:09
that doesn't say anything about license or "ok to
scottmg
2016/06/08 02:28:18
Hmm, true. I'll see if I can find something simila
|
| +// by Rick Regan. |
| +std::string FpToBin(double fp) { |
| + double fp_int; |
| + double fp_frac = modf(fp, &fp_int); |
| + |
| + std::string result; |
| + if (fp_int != 0) { |
| + std::string integral; |
| + do { |
| + integral += '0' + static_cast<int>(fmod(fp_int, 2)); |
| + fp_int = floor(fp_int / 2); |
| + } while (fp_int > 0); |
| + std::reverse(integral.begin(), integral.end()); |
| + result += integral; |
| + } else { |
| + result += "0"; |
| + } |
| + |
| + result += "."; |
| + |
| + if (fp_frac != 0) { |
| + std::string fractional; |
| + while (fp_frac > 0) { |
| + fp_frac *= 2; |
| + double integral_part; |
| + fp_frac = modf(fp_frac, &integral_part); |
| + fractional += '0' + static_cast<int>(integral_part); |
| + } |
| + result += fractional; |
| + } else { |
| + result += "0"; |
| + } |
| + |
| + return result; |
| +} |
| + |
| +TEST(StringNumberConversionsTest, TestFpToBin) { |
| + EXPECT_EQ(FpToBin(16), "10000.0"); |
| + EXPECT_EQ(FpToBin(0.00390625), "0.00000001"); |
| + EXPECT_EQ(FpToBin(25), "11001.0"); |
| + EXPECT_EQ(FpToBin(0.1), |
| + "0.0001100110011001100110011001100110011001100110011001101"); |
| + EXPECT_EQ(FpToBin(0.6), |
| + "0.10011001100110011001100110011001100110011001100110011"); |
| +} |
| + |
| +// Test cases of known-bad strtod conversions that motivated the use of dmg_fp. |
| +// See https://bugs.chromium.org/p/chromium/issues/detail?id=593512. |
| +TEST(StringNumberConversionsTest, StrtodFailures) { |
| + static const struct { |
| + const char* input; |
| + const char* expected; |
| + } cases[] = { |
| + // http://www.exploringbinary.com/incorrectly-rounded-conversions-in-visual-c-plus-plus/ |
| + {"9214843084008499", |
| + "100000101111001101100111011000101011101110110000110100.0"}, |
|
Nico
2016/06/08 00:45:09
could we use hexfloats for the expecteds instead?
scottmg
2016/06/08 02:28:18
VS doesn't seem to support hex floating point lite
scottmg
2016/06/08 02:36:04
No such luck.
d:\src\x>type fp.c
#include <stdio.
|
| + {"0.500000000000000166533453693773481063544750213623046875", |
| + "0.1000000000000000000000000000000000000000000000000001"}, |
| + {"30078505129381147446200", |
| + "1100101111010001111000111001001110001101100000010000100000000000000" |
| + "00000000.0"}, |
| + {"1777820000000000000001", |
| + "1100000011000000011010101101110101101001011100011111000000000000000" |
| + "0000.0"}, |
| + {"0." |
| + "500000000000000166547006220929549868969843373633921146392822265625", |
| + "0.1000000000000000000000000000000000000000000000000001"}, |
| + {"0." |
| + "50000000000000016656055874808561867439493653364479541778564453125", |
| + "0.1000000000000000000000000000000000000000000000000001"}, |
| + {"0.3932922657273", |
| + "0.01100100101011101100110101001011000100011000100011101"}, |
| + |
| + // http://www.exploringbinary.com/incorrectly-rounded-conversions-in-gcc-and-glibc/ |
| + {"0.500000000000000166533453693773481063544750213623046875", |
| + "0.1000000000000000000000000000000000000000000000000001"}, |
| + {"3.518437208883201171875e13", |
| + "1000000000000000000000000000000000000000000000.000001"}, |
| + {"62.5364939768271845828", |
| + "111110.100010010101011110101011010101001111100101001"}, |
| + {"8.10109172351e-10", |
| + "0." |
| + "0000000000000000000000000000001101111010101110010111010111011110000" |
| + "11111101000011"}, |
| + {"1.50000000000000011102230246251565404236316680908203125", "1.1"}, |
| + {"9007199254740991.4999999999999999999999999999999995", |
| + "11111111111111111111111111111111111111111111111111111.0"}, |
| + |
| + // http://www.exploringbinary.com/incorrect-decimal-to-floating-point-conversion-in-sqlite/ |
| + {"1e-23", |
| + /* 0x1.82db34012b251p-77 */ "0." |
| + "0000000000000000000000000000000000000000000" |
| + "0000000000000000000000000000000001100000101" |
| + "101101100110100000000010010101100100101000" |
| + "1"}, |
| + {"8.533e+68", |
| + /* 0x1.fa69165a8eea2p+228 */ "111111010011010010001011001011010100011101" |
| + "110101000100000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "0000000000000000000.0"}, |
| + {"4.1006e-184", |
| + /* 0x1.be0d1c7ea60c9p-610 */ "0." |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000110111110000011010001" |
| + "11000111111010100110000011001001"}, |
| + {"9.998e+307", |
| + /* 0x1.1cc0a350ca87bp+1023 */ "10001110011000000101000110101000011001010" |
| + "10000111101100000000000000000000000000000" |
| + "00000000000000000000000000000000000000000" |
| + "00000000000000000000000000000000000000000" |
| + "00000000000000000000000000000000000000000" |
| + "00000000000000000000000000000000000000000" |
| + "00000000000000000000000000000000000000000" |
| + "00000000000000000000000000000000000000000" |
| + "00000000000000000000000000000000000000000" |
| + "00000000000000000000000000000000000000000" |
| + "00000000000000000000000000000000000000000" |
| + "00000000000000000000000000000000000000000" |
| + "00000000000000000000000000000000000000000" |
| + "00000000000000000000000000000000000000000" |
| + "00000000000000000000000000000000000000000" |
| + "00000000000000000000000000000000000000000" |
| + "00000000000000000000000000000000000000000" |
| + "00000000000000000000000000000000000000000" |
| + "00000000000000000000000000000000000000000" |
| + "00000000000000000000000000000000000000000" |
| + "00000000000000000000000000000000000000000" |
| + "00000000000000000000000000000000000000000" |
| + "00000000000000000000000000000000000000000" |
| + "00000000000000000000000000000000000000000" |
| + "0000000000000000000000000000000000000000." |
| + "0"}, |
| + {"9.9538452227e-280", |
| + /* 0x1.2117ae45cde43p-927 */ "0." |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "001001000010001011110101110010001011100110" |
| + "1111001000011"}, |
| + {"6.47660115e-260", |
| + /* 0x1.fdd9e333badadp-862 */ "0." |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000111111101110110011110" |
| + "00110011001110111010110110101101"}, |
| + {"7.4e+47", |
| + /* 0x1.033d7eca0adefp+159 */ "100000011001111010111111011001010000010101" |
| + "101111011110000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "0000000000000000000000000000000000.0"}, |
| + {"5.92e+48", |
| + /* 0x1.033d7eca0adefp+162 */ "100000011001111010111111011001010000010101" |
| + "101111011110000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "0000000000000000000000000000000000000.0"}, |
| + {"7.35e+66", |
| + /* 0x1.172b70eababa9p+222 */ "100010111001010110111000011101010101110101" |
| + "011101010010000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "0000000000000.0"}, |
| + {"8.32116e+55", |
| + /* 0x1.b2628393e02cdp+185 */ "110110010011000101000001110010011111000000" |
| + "010110011010000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000" |
| + "000000000000000000.0"}, |
| + }; |
| + |
| + for (const auto& test : cases) { |
| + double output; |
| + EXPECT_TRUE(StringToDouble(test.input, &output)); |
| + EXPECT_EQ(FpToBin(output), test.expected); |
| + } |
| +} |
| + |
| } // namespace base |