From 7d9108a0795b8d90013bb86fe00824d2195a78e3 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 12 Dec 2015 00:55:28 +0100 Subject: [PATCH] diagnostics formatting helper: set limited precision for doubles this deals with a recurring problem in test code: very common "simple" fractional values can not be represented precisely as binary floating point. The classical example is 0.1 Since this is a diagnostics facility, we can cheat around this insidious problem by just setting a limited rendering precision. Floating point numbers behave deterministic; you just need to know how to deal with limited precision. --- src/lib/format-util.hpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/lib/format-util.hpp b/src/lib/format-util.hpp index ef472797d..5063d8aaf 100644 --- a/src/lib/format-util.hpp +++ b/src/lib/format-util.hpp @@ -71,6 +71,9 @@ namespace util { namespace { // we need to guard the string conversion // to avoid a compiler error in case the type isn't convertible.... + // precision for rendering of double values + const auto DIAGNOSTICS_DOUBLE_PRECISION = 8; + template struct use_StringConversion : can_ToString { }; @@ -108,6 +111,26 @@ namespace util { try { return boost::lexical_cast (val); } catch(...) { return ""; } }; + + /** explicit specialisation to control precision of double values. + * @note we set an explicit precision, since this is a diagnostic facility + * and we typically do not want to see all digits, but, for test code, + * we do want a predictable string representation of simple fractional + * values like `0.1` (which can not be represented as binary floats) + */ + template<> + struct _InvokeFailsafe + { + static string + toString (double const& val) + try { + std::ostringstream buffer; + buffer.precision(DIAGNOSTICS_DOUBLE_PRECISION); + buffer << val; + return buffer.str(); + } + catch(...) { return ""; } + }; }//(End) guards/helpers