Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON representation for floating point values has too many digits #1109

Closed
grebenyukaa opened this issue May 25, 2018 · 6 comments
Closed

JSON representation for floating point values has too many digits #1109

grebenyukaa opened this issue May 25, 2018 · 6 comments
Labels
kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation

Comments

@grebenyukaa
Copy link

The values of type "float" seem to be internally treated as values of type "double". This leads to an issue with their text representation. For example, the snippet below:

json j;
j["test"] = 0.42f;
std::cout << j.dump() << std::endl;

produces this json output:

{"test":0.41999998688697815}

I experimented a bit with float values, and found out, that a workaround, like that:

namespace nlohmann
{
    namespace detail
   {
        template<>
        inline char* to_chars<json::number_float_t>(char* first, char* last, json::number_float_t value)
        {
            std::ostringstream s;
            s << value;
            std::string buf = oss.str();
            return std::copy(buf.begin(), buf.end(), first);
        }
    }
}

can impove floats' representation, and produce the following json:

{"test":0.42}

I know, that floating point arithmetics is a sensitive topic, but I think, floats' representation in human-readable format should be improved, if possible.

  • Compiler: Microsoft Visual C++ 2015
  • Release: 3.1.2
@OvermindDL1
Copy link

Isn't JSON pretty well known (if not defined) as having floats being 64-bit, I.E. C++ doubles?

Also ostringstream streaming is sloooooooow, if anything is performance sensitive you don't want to use it.

@gregmarr
Copy link
Contributor

A lot of work has been put into both the performance and correctness of the current code.

The default floating point storage type is indeed double, and all values are converted to it before storage. The fact that it's single precision is lost long before you convert to text. While your code works for that one particular value, it is wrong for many more values as it loses precision.

@nlohmann
Copy link
Owner

As @gregmarr stated, that behavior is intended. You may want to try to give float as template argument to the basic_json class.

@grebenyukaa
Copy link
Author

Thanks for the hint about template argument, I'll try it - I overlooked this option somehow!

@nlohmann
Copy link
Owner

Example:

#include <iostream>
#include "json.hpp"

int main() {
    using json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, float>;

    json j;
    j["test"] = 0.42f;
    std::cout << j.dump() << std::endl;
}

Output:

{"test":0.42}

@nlohmann nlohmann added kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation labels May 26, 2018
@nlohmann nlohmann closed this as completed Jun 7, 2018
@jonesydev
Copy link

Thanks for the fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation
Projects
None yet
Development

No branches or pull requests

5 participants