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 |