diff --git a/src/error-handlers/multipleOf.js b/src/error-handlers/multipleOf.js index 5589929..04980d0 100644 --- a/src/error-handlers/multipleOf.js +++ b/src/error-handlers/multipleOf.js @@ -39,18 +39,29 @@ const multipleOfErrorHandler = async (normalizedErrors, instance, localization) return errors; }; +/** + * @param {number} value + * @returns {number} + */ +const countDecimals = (value) => value.toString().split(".")[1]?.length || 0; + /** * @param {number} a * @param {number} b * @returns {number} */ const gcd = (a, b) => { - while (b !== 0) { - const temp = b; - b = a % b; - a = temp; + const m = 10 ** Math.max(countDecimals(a), countDecimals(b)); + let x = Math.round(a * m); + let y = Math.round(b * m); + + while (y !== 0) { + const temp = y; + y = x % y; + x = temp; } - return Math.abs(a); + + return Math.abs(x) / m; }; /** @@ -59,7 +70,11 @@ const gcd = (a, b) => { * @returns {number} */ const lcm = (a, b) => { - return Math.abs(a * b) / gcd(a, b); + const m = 10 ** Math.max(countDecimals(a), countDecimals(b)); + const x = Math.round(a * m); + const y = Math.round(b * m); + + return Math.abs(x * y) / (gcd(x, y) * m); }; export default multipleOfErrorHandler; diff --git a/src/test-suite/tests/multipleOf.json b/src/test-suite/tests/multipleOf.json index 766f089..067638d 100644 --- a/src/test-suite/tests/multipleOf.json +++ b/src/test-suite/tests/multipleOf.json @@ -44,6 +44,24 @@ "schemaLocations": ["#/allOf/0/multipleOf", "#/allOf/1/multipleOf", "#/allOf/2/multipleOf"] } ] + }, + { + "description": "multiple decimal multipleOf constraints (LCM of 0.2 and 0.3)", + "schema": { + "allOf": [ + { "multipleOf": 0.2 }, + { "multipleOf": 0.3 } + ] + }, + "instance": 0.7, + "errors": [ + { + "messageId": "multipleOf-message", + "messageParams": { "multipleOf": "0.6" }, + "instanceLocation": "#", + "schemaLocations": ["#/allOf/0/multipleOf", "#/allOf/1/multipleOf"] + } + ] } ] }