Skip to content

Commit e3aa397

Browse files
authored
fix: validate multipleOf fails on float-point value (#295)
* fix: validate multipleOf fails on float-point value * make clang-tidy happy. * fix test case error when multipleOf is float but number is int * fix multiple of float number
1 parent c6fefb8 commit e3aa397

File tree

4 files changed

+42
-0
lines changed

4 files changed

+42
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ cmake-build-*
44
venv
55
env
66
compile_commands.json
7+
.vs/*

src/json-validator.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -864,7 +864,12 @@ class numeric : public schema
864864
bool violates_multiple_of(T x) const
865865
{
866866
double res = std::remainder(x, multipleOf_.second);
867+
double multiple = std::fabs(x / multipleOf_.second);
868+
if (multiple > 1) {
869+
res = res / multiple;
870+
}
867871
double eps = std::nextafter(x, 0) - static_cast<double>(x);
872+
868873
return std::fabs(res) > std::fabs(eps);
869874
}
870875

test/CMakeLists.txt

+4
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ add_executable(issue-98 issue-98.cpp)
4343
target_link_libraries(issue-98 nlohmann_json_schema_validator)
4444
add_test(NAME issue-98-erase-exception-unknown-keywords COMMAND issue-98)
4545

46+
add_executable(issue-293 issue-293.cpp)
47+
target_link_libraries(issue-293 nlohmann_json_schema_validator)
48+
add_test(NAME issue-293-float-point-error COMMAND issue-293)
49+
4650
# Unit test for string format checks
4751
add_executable(string-format-check-test string-format-check-test.cpp)
4852
target_include_directories(string-format-check-test PRIVATE ${PROJECT_SOURCE_DIR}/src/)

test/issue-293.cpp

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#include "nlohmann/json-schema.hpp"
2+
3+
using nlohmann::json_schema::json_validator;
4+
5+
template <typename T>
6+
int should_throw(const nlohmann::json &schema, T value)
7+
{
8+
try {
9+
json_validator(schema).validate(value);
10+
} catch (const std::exception &ex) {
11+
return 0;
12+
}
13+
return 1;
14+
}
15+
16+
int main(void)
17+
{
18+
19+
json_validator({{"type", "number"}, {"multipleOf", 0.001}}).validate(0.3 - 0.2);
20+
json_validator({{"type", "number"}, {"multipleOf", 3.3}}).validate(8.0 - 1.4);
21+
json_validator({{"type", "number"}, {"multipleOf", 1000.01}}).validate((1000.03 - 0.02) * 15.0);
22+
json_validator({{"type", "number"}, {"multipleOf", 0.001}}).validate(0.030999999999999993);
23+
json_validator({{"type", "number"}, {"multipleOf", 0.100000}}).validate(1.9);
24+
json_validator({{"type", "number"}, {"multipleOf", 100000.1}}).validate(9000009);
25+
26+
int exc_count = 0;
27+
exc_count += should_throw({{"type", "number"}, {"multipleOf", 0.001}}, 0.3 - 0.2005);
28+
exc_count += should_throw({{"type", "number"}, {"multipleOf", 1000.02}}, (1000.03 - 0.02) * 15.0);
29+
exc_count += should_throw({{"type", "number"}, {"multipleOf", 100000.11}}, 9000009);
30+
31+
return exc_count;
32+
}

0 commit comments

Comments
 (0)