File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -984,9 +984,14 @@ generate_validator = function(ctx, schema)
984984 -- integer multipleOf: modulo is enough
985985 ctx :stmt (sformat (' if %s %% %d ~= 0 then' , ctx :param (1 ), mof ))
986986 else
987- -- float multipleOf: it's a bit more hacky and slow
987+ -- float multipleOf: use relative tolerance to handle IEEE 754
988+ -- precision errors. e.g. 1.13 / 0.01 = 112.99999999999999
989+ -- We check whether the fractional part of the quotient is
990+ -- negligible relative to its magnitude.
988991 ctx :stmt (sformat (' local quotient = %s / %s' , ctx :param (1 ), mof ))
989- ctx :stmt (sformat (' if %s(quotient) ~= quotient then' , ctx :libfunc (' math.modf' )))
992+ ctx :stmt (sformat (' local rounded = %s(quotient + 0.5)' , ctx :libfunc (' math.floor' )))
993+ ctx :stmt ( ' local tol = 1e-12 * (rounded == 0 and 1 or (rounded < 0 and -rounded or rounded))' )
994+ ctx :stmt (sformat (' if %s(quotient - rounded) > tol then' , ctx :libfunc (' math.abs' )))
990995 end
991996 ctx :stmt (sformat ( ' return false, %s("expected %%s to be a multiple of %s", %s)' ,
992997 ctx :libfunc (' string.format' ), mof , ctx :param (1 )))
Original file line number Diff line number Diff line change 1+ [
2+ {
3+ "description" : " multipleOf with float precision" ,
4+ "schema" : {
5+ "type" : " number" ,
6+ "multipleOf" : 0.01
7+ },
8+ "tests" : [
9+ {
10+ "description" : " 1.13 is a multiple of 0.01" ,
11+ "data" : 1.13 ,
12+ "valid" : true
13+ },
14+ {
15+ "description" : " 0.01 is a multiple of 0.01" ,
16+ "data" : 0.01 ,
17+ "valid" : true
18+ },
19+ {
20+ "description" : " 100.05 is a multiple of 0.01" ,
21+ "data" : 100.05 ,
22+ "valid" : true
23+ },
24+ {
25+ "description" : " 1.1312 is not a multiple of 0.01" ,
26+ "data" : 1.1312 ,
27+ "valid" : false
28+ },
29+ {
30+ "description" : " 0.015 is not a multiple of 0.01" ,
31+ "data" : 0.015 ,
32+ "valid" : false
33+ }
34+ ]
35+ },
36+ {
37+ "description" : " multipleOf with integer" ,
38+ "schema" : {
39+ "type" : " number" ,
40+ "multipleOf" : 3
41+ },
42+ "tests" : [
43+ {
44+ "description" : " 9 is a multiple of 3" ,
45+ "data" : 9 ,
46+ "valid" : true
47+ },
48+ {
49+ "description" : " 10 is not a multiple of 3" ,
50+ "data" : 10 ,
51+ "valid" : false
52+ }
53+ ]
54+ },
55+ {
56+ "description" : " multipleOf with large values" ,
57+ "schema" : {
58+ "type" : " number" ,
59+ "multipleOf" : 1000000000.5
60+ },
61+ "tests" : [
62+ {
63+ "description" : " exact large multiple is valid" ,
64+ "data" : 2000000001.0 ,
65+ "valid" : true
66+ },
67+ {
68+ "description" : " large value offset by 0.05 is invalid" ,
69+ "data" : 1000000000.55 ,
70+ "valid" : false
71+ }
72+ ]
73+ }
74+ ]
Original file line number Diff line number Diff line change @@ -47,6 +47,7 @@ local supported = {
4747 " spec/extra/dependencies.json" ,
4848 " spec/extra/table.json" ,
4949 " spec/extra/ref.json" ,
50+ " spec/extra/multipleOf.json" ,
5051
5152 ' spec/JSON-Schema-Test-Suite/tests/draft4/type.json' ,
5253 ' spec/JSON-Schema-Test-Suite/tests/draft4/default.json' ,
Original file line number Diff line number Diff line change @@ -50,6 +50,7 @@ local supported = {
5050 " spec/extra/ref.json" ,
5151 " spec/extra/format.json" ,
5252 " spec/extra/default.json" ,
53+ " spec/extra/multipleOf.json" ,
5354
5455 ' spec/JSON-Schema-Test-Suite/tests/draft7/type.json' ,
5556 ' spec/JSON-Schema-Test-Suite/tests/draft7/default.json' ,
You can’t perform that action at this time.
0 commit comments