Skip to content

Commit 671315b

Browse files
authored
Fix: incorrect combined multipleOf when using decimal constraints (#156)
* updated the lcm logic with decimal-aware and test case is added * test is fixed * fix: whitespace cleanup * fix: revert formatting changes
1 parent cde874a commit 671315b

2 files changed

Lines changed: 39 additions & 6 deletions

File tree

src/error-handlers/multipleOf.js

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,29 @@ const multipleOfErrorHandler = async (normalizedErrors, instance, localization)
3939
return errors;
4040
};
4141

42+
/**
43+
* @param {number} value
44+
* @returns {number}
45+
*/
46+
const countDecimals = (value) => value.toString().split(".")[1]?.length || 0;
47+
4248
/**
4349
* @param {number} a
4450
* @param {number} b
4551
* @returns {number}
4652
*/
4753
const gcd = (a, b) => {
48-
while (b !== 0) {
49-
const temp = b;
50-
b = a % b;
51-
a = temp;
54+
const m = 10 ** Math.max(countDecimals(a), countDecimals(b));
55+
let x = Math.round(a * m);
56+
let y = Math.round(b * m);
57+
58+
while (y !== 0) {
59+
const temp = y;
60+
y = x % y;
61+
x = temp;
5262
}
53-
return Math.abs(a);
63+
64+
return Math.abs(x) / m;
5465
};
5566

5667
/**
@@ -59,7 +70,11 @@ const gcd = (a, b) => {
5970
* @returns {number}
6071
*/
6172
const lcm = (a, b) => {
62-
return Math.abs(a * b) / gcd(a, b);
73+
const m = 10 ** Math.max(countDecimals(a), countDecimals(b));
74+
const x = Math.round(a * m);
75+
const y = Math.round(b * m);
76+
77+
return Math.abs(x * y) / (gcd(x, y) * m);
6378
};
6479

6580
export default multipleOfErrorHandler;

src/test-suite/tests/multipleOf.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,24 @@
4444
"schemaLocations": ["#/allOf/0/multipleOf", "#/allOf/1/multipleOf", "#/allOf/2/multipleOf"]
4545
}
4646
]
47+
},
48+
{
49+
"description": "multiple decimal multipleOf constraints (LCM of 0.2 and 0.3)",
50+
"schema": {
51+
"allOf": [
52+
{ "multipleOf": 0.2 },
53+
{ "multipleOf": 0.3 }
54+
]
55+
},
56+
"instance": 0.7,
57+
"errors": [
58+
{
59+
"messageId": "multipleOf-message",
60+
"messageParams": { "multipleOf": "0.6" },
61+
"instanceLocation": "#",
62+
"schemaLocations": ["#/allOf/0/multipleOf", "#/allOf/1/multipleOf"]
63+
}
64+
]
4765
}
4866
]
4967
}

0 commit comments

Comments
 (0)