diff options
author | Abseil Team <absl-team@google.com> | 2022-11-16 17:17:58 (GMT) |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2022-11-16 17:18:37 (GMT) |
commit | 9c332145b71c36a5bad9688312c79184f98601ff (patch) | |
tree | f465e472334c8dd173ff3cfb76823ed1f18a7f36 | |
parent | 4408a0288b24fbe9156a9b14bbecd148ea64f40f (diff) | |
download | googletest-9c332145b71c36a5bad9688312c79184f98601ff.zip googletest-9c332145b71c36a5bad9688312c79184f98601ff.tar.gz googletest-9c332145b71c36a5bad9688312c79184f98601ff.tar.bz2 |
When printing floating-point numbers, print full precision by default.
To make debug output readable, we still use the faster 6-digit precision
sometimes, but only if it will round-trip.
This way, when a test fails due to a very small difference in floating-point
numbers, users will have enough digits to see the difference.
PiperOrigin-RevId: 488958311
Change-Id: Ibcac43f48a97006d89217530c69386cc4fa2735c
-rw-r--r-- | googletest/include/gtest/gtest-printers.h | 75 | ||||
-rw-r--r-- | googletest/test/googletest-printers-test.cc | 10 |
2 files changed, 84 insertions, 1 deletions
diff --git a/googletest/include/gtest/gtest-printers.h b/googletest/include/gtest/gtest-printers.h index 89215e6..eeaef04 100644 --- a/googletest/include/gtest/gtest-printers.h +++ b/googletest/include/gtest/gtest-printers.h @@ -484,6 +484,81 @@ GTEST_API_ void PrintTo(__uint128_t v, ::std::ostream* os); GTEST_API_ void PrintTo(__int128_t v, ::std::ostream* os); #endif // __SIZEOF_INT128__ +// The default resolution used to print floating-point values uses only +// 6 digits, which can be confusing if a test compares two values whose +// difference lies in the 7th digit. So we'd like to print out numbers +// in full precision. +// However if the value is something simple like 1.1, full will print a +// long string like 1.100000001 due to floating-point numbers not using +// a base of 10. This routiune returns an appropriate resolution for a +// given floating-point number, that is, 6 if it will be accurate, or a +// max_digits10 value (full precision) if it won't, for values between +// 0.0001 and one million. +// It does this by computing what those digits would be (by multiplying +// by an appropriate power of 10), then dividing by that power again to +// see if gets the original value back. +// A similar algorithm applies for values larger than one million; note +// that for those values, we must divide to get a six-digit number, and +// then multiply to possibly get the original value again. +template <typename FloatType> +int AppropriateResolution(FloatType val) { + int full = std::numeric_limits<FloatType>::max_digits10; + if (val < 0) val = -val; + + if (val < 1000000) { + FloatType mulfor6 = 1e10; + if (val >= 100000.0) { // 100,000 to 999,999 + mulfor6 = 1.0; + } else if (val >= 10000.0) { + mulfor6 = 1e1; + } else if (val >= 1000.0) { + mulfor6 = 1e2; + } else if (val >= 100.0) { + mulfor6 = 1e3; + } else if (val >= 10.0) { + mulfor6 = 1e4; + } else if (val >= 1.0) { + mulfor6 = 1e5; + } else if (val >= 0.1) { + mulfor6 = 1e6; + } else if (val >= 0.01) { + mulfor6 = 1e7; + } else if (val >= 0.001) { + mulfor6 = 1e8; + } else if (val >= 0.0001) { + mulfor6 = 1e9; + } + if (static_cast<int32_t>(val * mulfor6 + 0.5) / mulfor6 == val) return 6; + } else if (val < 1e10) { + FloatType divfor6 = 1.0; + if (val >= 1e9) { // 1,000,000,000 to 9,999,999,999 + divfor6 = 10000; + } else if (val >= 1e8) { // 100,000,000 to 999,999,999 + divfor6 = 1000; + } else if (val >= 1e7) { // 10,000,000 to 99,999,999 + divfor6 = 100; + } else if (val >= 1e6) { // 1,000,000 to 9,999,999 + divfor6 = 10; + } + if (static_cast<int32_t>(val / divfor6 + 0.5) * divfor6 == val) return 6; + } + return full; +} + +inline void PrintTo(float f, ::std::ostream* os) { + auto old_precision = os->precision(); + os->precision(AppropriateResolution(f)); + *os << f; + os->precision(old_precision); +} + +inline void PrintTo(double d, ::std::ostream* os) { + auto old_precision = os->precision(); + os->precision(AppropriateResolution(d)); + *os << d; + os->precision(old_precision); +} + // Overloads for C strings. GTEST_API_ void PrintTo(const char* s, ::std::ostream* os); inline void PrintTo(char* s, ::std::ostream* os) { diff --git a/googletest/test/googletest-printers-test.cc b/googletest/test/googletest-printers-test.cc index d2d88a5..8a7db25 100644 --- a/googletest/test/googletest-printers-test.cc +++ b/googletest/test/googletest-printers-test.cc @@ -458,7 +458,15 @@ TEST(PrintBuiltInTypeTest, Int128) { // Floating-points. TEST(PrintBuiltInTypeTest, FloatingPoints) { - EXPECT_EQ("1.5", Print(1.5f)); // float + // float (32-bit precision) + EXPECT_EQ("1.5", Print(1.5f)); + + EXPECT_EQ("1.0999999", Print(1.09999990f)); + EXPECT_EQ("1.1", Print(1.10000002f)); + EXPECT_EQ("1.10000014", Print(1.10000014f)); + EXPECT_EQ("9e+09", Print(9e9f)); + + // double EXPECT_EQ("-2.5", Print(-2.5)); // double } |