 Chromium Code Reviews
 Chromium Code Reviews Issue 2044643005:
  Add strtod test cases  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master
    
  
    Issue 2044643005:
  Add strtod test cases  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master| 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 |