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

Is there a way to control the precision of serialized floating point numbers? #677

Closed
gonzalobenegas opened this issue Aug 4, 2017 · 17 comments
Labels
kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation 🔮 V4 candidate A feature that should be discussed for the next major release

Comments

@gonzalobenegas
Copy link

I currently see doubles are being serialized with 16 significant figures. Is there any way to serialize them using, say, 6 significant figures?

@gregmarr
Copy link
Contributor

gregmarr commented Aug 4, 2017

That would cause values to change in a round trip. Is that really what you want?

@gonzalobenegas
Copy link
Author

Yes, I just don't need that much precision and I want to save storage space.

@gonzalobenegas
Copy link
Author

Maybe by modifying the source code?

@nlohmann
Copy link
Owner

nlohmann commented Aug 8, 2017

There is no parameter for this, and I doubt that adding one would be beneficial for a lot of users. What you could do is to edit function dump_float() and change line

// get number of digits for a text -> float -> text round-trip
static constexpr auto d = std::numeric_limits<number_float_t>::digits10;

to the number of digits you like.

@nlohmann nlohmann added the solution: proposed fix a fix for the issue has been proposed and waits for confirmation label Aug 8, 2017
@gonzalobenegas
Copy link
Author

Thanks, that works for my case!

@psiha
Copy link

psiha commented Oct 4, 2018

Not all text-serialized-JSON usage is about round-triping, e.g. sometimes it is used for structured reports - and printing out all the decimals in a double when you are say presenting benchmark results in milliseconds is just very very ugly noise...
For example with RapidJSON one can say writer.SetMaxDecimalPlaces( 1 )...please consider adding something along those lines (it can even be a compile time option/template parameter as far as I am concerned).

@ziggurat29
Copy link

seconded; I don't need to report time with picosecond precision only to add 50% overhead to my docs. I would prefer a runtime setting.

@nathanieltagg
Copy link

This is a major limitation for my application: it ships a LOT of floating point numbers, and so I have to tune the precision of each number in at least two ways: precision to a certain fractional uncertainty, or precision to a specific decimal-place precision. The goal is maximum precision with fewest characters, so I make liberal use of scientific notation to achieve this in some cases.

To implement my solution in your framework, I just need one hook: the ability to assign an unquoted string. That is:
j['mything'] = json::unquoted_string("1.11")
would yield:
{
mything: 1.11
}

Would this be possible?

@p-i-
Copy link

p-i- commented Jan 23, 2019

I would love something like:
my_json.dump( "pretty_print=true, indent=4, float_decimal_places=2, float_use_scientific_notation=false" )

The option-string would almost be JSON too.

@nathanieltagg
Copy link

@p-i- You can manage that with a custom streamer class, I think. Might be easy to tack on.

@nathanieltagg
Copy link

Thinking more about it, I think the method I use in my hack actually would work for the custom-output thing. You declare a bunch more primative types - instead of just a single floating-point class, you also have a fixed-point-2decimal, fixed-point-3decimal, etc. They act just like the regular float classes during interactions, but the streamer can see them and act accordingly.

Another possibility would be adding to each basic_json another field, which could be an instance of an (empty) struct. The struct template would determine streamer flow, i.e.
struct FixedPoint<2> {}
where template parameters could be used to set options or specificity. This is infinitely expandable and doesn't require an enum like value_t does.... but does increase storage for simple types.

@CraigHutchinson
Copy link

Has a solution to this issue ever been made into the core master?

@t-b
Copy link
Contributor

t-b commented Oct 9, 2019

@CraigHutchinson Nope.

@yalov
Copy link

yalov commented Sep 26, 2024

The feature is so highly requested, that ChatGPT belives it's already there ;)

// CHATGPT GENERATED, WILL NOT WORK
#include <iostream>
#include <nlohmann/json.hpp>

int main() {
    // Create a JSON object
    nlohmann::json j;
    j["pi"] = 3.14159265358979323846;
    j["e"] = 2.718281828459045;

    // Serialize JSON with custom precision (indentation level 4 and ensure_precision enabled)
    std::cout << j.dump(4, ' ', false, nlohmann::json::error_handler_t::strict, 4) << '\n';

    return 0;
}

@nlohmann is there any possibility that you'll reconsider the feature request based on the support #677 (comment) , and
#1170

@RaidenV
Copy link

RaidenV commented Oct 5, 2024

This needs some sort of fix. Translation from an easily representable floating point number like 1100.000 gets corrupted to 1099.9999999999989 when translating to JSON.

@gregmarr
Copy link
Contributor

@RaidenV Do you have sample code showing the error?

@lingxd
Copy link

lingxd commented Nov 28, 2024

该功能的需求非常强烈,以至于 ChatGPT 认为它已经存在了 ;)

// CHATGPT GENERATED, WILL NOT WORK
#include <iostream>
#include <nlohmann/json.hpp>

int main() {
    // Create a JSON object
    nlohmann::json j;
    j["pi"] = 3.14159265358979323846;
    j["e"] = 2.718281828459045;

    // Serialize JSON with custom precision (indentation level 4 and ensure_precision enabled)
    std::cout << j.dump(4, ' ', false, nlohmann::json::error_handler_t::strict, 4) << '\n';

    return 0;
}

@nlohmann 您是否有可能根据支持#677(评论)#1170重新考虑该功能请求

I really need this function

@nlohmann nlohmann added the 🔮 V4 candidate A feature that should be discussed for the next major release label Nov 28, 2024
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 🔮 V4 candidate A feature that should be discussed for the next major release
Projects
None yet
Development

No branches or pull requests