diff --git a/include/nlohmann/detail/output/binary_writer.hpp b/include/nlohmann/detail/output/binary_writer.hpp index c507134c..b8b5a572 100644 --- a/include/nlohmann/detail/output/binary_writer.hpp +++ b/include/nlohmann/detail/output/binary_writer.hpp @@ -194,7 +194,8 @@ class binary_writer } else { - if (j.m_value.number_float < std::numeric_limits::max() and + if (j.m_value.number_float > -std::numeric_limits::min() and + j.m_value.number_float < std::numeric_limits::max() and static_cast(static_cast(j.m_value.number_float)) == j.m_value.number_float) { oa->write_character(get_cbor_float_prefix(static_cast(j.m_value.number_float))); diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 6c339c84..23ae8105 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -12143,7 +12143,8 @@ class binary_writer } else { - if (j.m_value.number_float < std::numeric_limits::max() and + if (j.m_value.number_float > -std::numeric_limits::min() and + j.m_value.number_float < std::numeric_limits::max() and static_cast(static_cast(j.m_value.number_float)) == j.m_value.number_float) { oa->write_character(get_cbor_float_prefix(static_cast(j.m_value.number_float))); diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index 40fe109a..531f56d7 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -834,7 +834,7 @@ TEST_CASE("CBOR") } } - SECTION("float") + SECTION("double-precision float") { SECTION("3.1415925") { @@ -853,6 +853,10 @@ TEST_CASE("CBOR") CHECK(json::from_cbor(result, true, false) == j); } + } + + SECTION("single-precision float") + { SECTION("0.5") { double v = 0.5; @@ -867,6 +871,58 @@ TEST_CASE("CBOR") CHECK(json::from_cbor(result) == j); CHECK(json::from_cbor(result) == v); } + SECTION("0.0") + { + double v = 0.0; + json j = v; + // its double-precision binary value is: + // {0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + std::vector expected = {0xfa, 0x00, 0x00, 0x00, 0x00}; + const auto result = json::to_cbor(j); + CHECK(result == expected); + // roundtrip + CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result) == v); + } + SECTION("-0.0") + { + double v = -0.0; + json j = v; + // its double-precision binary value is: + // {0xfb, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + std::vector expected = {0xfa, 0x80, 0x00, 0x00, 0x00}; + const auto result = json::to_cbor(j); + CHECK(result == expected); + // roundtrip + CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result) == v); + } + SECTION("100.0") + { + double v = 100.0; + json j = v; + // its double-precision binary value is: + // {0xfb, 0x40, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + std::vector expected = {0xfa, 0x42, 0xc8, 0x00, 0x00}; + const auto result = json::to_cbor(j); + CHECK(result == expected); + // roundtrip + CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result) == v); + } + SECTION("200.0") + { + double v = 200.0; + json j = v; + // its double-precision binary value is: + // {0xfb, 0x40, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + std::vector expected = {0xfa, 0x43, 0x48, 0x00, 0x00}; + const auto result = json::to_cbor(j); + CHECK(result == expected); + // roundtrip + CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result) == v); + } } SECTION("half-precision float (edge cases)")