From 5a74efa8c76e9ee7dcdf7b76478a09e774de7de6 Mon Sep 17 00:00:00 2001 From: Esther Wang Date: Tue, 12 Dec 2023 15:48:41 +0800 Subject: [PATCH] Fix comparision of two doubles One of multipleOf test failed because most floating-point numbers end up being slightly imprecise. And, the check of multipleOf with two double numbers using the dividend (a) and the result of multiplying the multiple after rounding down by the divisor (floor(|a|/|b|)*b) to compare. Change to using std::numeric_limits::epsilon to check the error of the division result. --- include/rapidjson/schema.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/include/rapidjson/schema.h b/include/rapidjson/schema.h index 25990b6..02a6d0f 100644 --- a/include/rapidjson/schema.h +++ b/include/rapidjson/schema.h @@ -1641,9 +1641,13 @@ private: bool CheckDoubleMultipleOf(Context& context, double d) const { double a = std::abs(d), b = std::abs(multipleOf_.GetDouble()); - double q = std::floor(a / b); - double r = a - q * b; - if (r > 0.0) { + double q = a / b; + double qRounded = std::floor(q + 0.5); + double scaledEpsilon = (q + qRounded) * std::numeric_limits::epsilon(); + double difference = std::abs(qRounded - q); + bool isMultiple = (difference <= scaledEpsilon) + || (difference < std::numeric_limits::min()); + if (!isMultiple) { context.error_handler.NotMultipleOf(d, multipleOf_); RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMultipleOf); }