Skip to content

Commit 9c33214

Browse files
Abseil Teamcopybara-github
Abseil Team
authored andcommitted
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
1 parent 4408a02 commit 9c33214

File tree

2 files changed

+84
-1
lines changed

2 files changed

+84
-1
lines changed

googletest/include/gtest/gtest-printers.h

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,81 @@ GTEST_API_ void PrintTo(__uint128_t v, ::std::ostream* os);
484484
GTEST_API_ void PrintTo(__int128_t v, ::std::ostream* os);
485485
#endif // __SIZEOF_INT128__
486486

487+
// The default resolution used to print floating-point values uses only
488+
// 6 digits, which can be confusing if a test compares two values whose
489+
// difference lies in the 7th digit. So we'd like to print out numbers
490+
// in full precision.
491+
// However if the value is something simple like 1.1, full will print a
492+
// long string like 1.100000001 due to floating-point numbers not using
493+
// a base of 10. This routiune returns an appropriate resolution for a
494+
// given floating-point number, that is, 6 if it will be accurate, or a
495+
// max_digits10 value (full precision) if it won't, for values between
496+
// 0.0001 and one million.
497+
// It does this by computing what those digits would be (by multiplying
498+
// by an appropriate power of 10), then dividing by that power again to
499+
// see if gets the original value back.
500+
// A similar algorithm applies for values larger than one million; note
501+
// that for those values, we must divide to get a six-digit number, and
502+
// then multiply to possibly get the original value again.
503+
template <typename FloatType>
504+
int AppropriateResolution(FloatType val) {
505+
int full = std::numeric_limits<FloatType>::max_digits10;
506+
if (val < 0) val = -val;
507+
508+
if (val < 1000000) {
509+
FloatType mulfor6 = 1e10;
510+
if (val >= 100000.0) { // 100,000 to 999,999
511+
mulfor6 = 1.0;
512+
} else if (val >= 10000.0) {
513+
mulfor6 = 1e1;
514+
} else if (val >= 1000.0) {
515+
mulfor6 = 1e2;
516+
} else if (val >= 100.0) {
517+
mulfor6 = 1e3;
518+
} else if (val >= 10.0) {
519+
mulfor6 = 1e4;
520+
} else if (val >= 1.0) {
521+
mulfor6 = 1e5;
522+
} else if (val >= 0.1) {
523+
mulfor6 = 1e6;
524+
} else if (val >= 0.01) {
525+
mulfor6 = 1e7;
526+
} else if (val >= 0.001) {
527+
mulfor6 = 1e8;
528+
} else if (val >= 0.0001) {
529+
mulfor6 = 1e9;
530+
}
531+
if (static_cast<int32_t>(val * mulfor6 + 0.5) / mulfor6 == val) return 6;
532+
} else if (val < 1e10) {
533+
FloatType divfor6 = 1.0;
534+
if (val >= 1e9) { // 1,000,000,000 to 9,999,999,999
535+
divfor6 = 10000;
536+
} else if (val >= 1e8) { // 100,000,000 to 999,999,999
537+
divfor6 = 1000;
538+
} else if (val >= 1e7) { // 10,000,000 to 99,999,999
539+
divfor6 = 100;
540+
} else if (val >= 1e6) { // 1,000,000 to 9,999,999
541+
divfor6 = 10;
542+
}
543+
if (static_cast<int32_t>(val / divfor6 + 0.5) * divfor6 == val) return 6;
544+
}
545+
return full;
546+
}
547+
548+
inline void PrintTo(float f, ::std::ostream* os) {
549+
auto old_precision = os->precision();
550+
os->precision(AppropriateResolution(f));
551+
*os << f;
552+
os->precision(old_precision);
553+
}
554+
555+
inline void PrintTo(double d, ::std::ostream* os) {
556+
auto old_precision = os->precision();
557+
os->precision(AppropriateResolution(d));
558+
*os << d;
559+
os->precision(old_precision);
560+
}
561+
487562
// Overloads for C strings.
488563
GTEST_API_ void PrintTo(const char* s, ::std::ostream* os);
489564
inline void PrintTo(char* s, ::std::ostream* os) {

googletest/test/googletest-printers-test.cc

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,15 @@ TEST(PrintBuiltInTypeTest, Int128) {
458458

459459
// Floating-points.
460460
TEST(PrintBuiltInTypeTest, FloatingPoints) {
461-
EXPECT_EQ("1.5", Print(1.5f)); // float
461+
// float (32-bit precision)
462+
EXPECT_EQ("1.5", Print(1.5f));
463+
464+
EXPECT_EQ("1.0999999", Print(1.09999990f));
465+
EXPECT_EQ("1.1", Print(1.10000002f));
466+
EXPECT_EQ("1.10000014", Print(1.10000014f));
467+
EXPECT_EQ("9e+09", Print(9e9f));
468+
469+
// double
462470
EXPECT_EQ("-2.5", Print(-2.5)); // double
463471
}
464472

0 commit comments

Comments
 (0)