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

Custom Precision on floating point numbers #1170

Closed
DarkZeros opened this issue Jul 19, 2018 · 18 comments
Closed

Custom Precision on floating point numbers #1170

DarkZeros opened this issue Jul 19, 2018 · 18 comments
Labels
state: stale the issue has not been updated in a while and will be closed automatically soon unless it is updated

Comments

@DarkZeros
Copy link
Contributor

DarkZeros commented Jul 19, 2018

When storing floating point values, exact representation is not possible.
ie: -0.2 -> -0.019999995827674866

However, when precision is not a big issue this introduces huge about of bloat in the JSON file. So there should be an option to specify how many characters of precision. Like it is possible in std::ostringstream (std::ostreams), and in printf.

Currently these 2 methods would be desired:

json j;
j["float"] = -0.123;
j.precision(2);
cout << j;
json j;
j["float"] = -0.123;
j.precision(2);
printf("%s", j.dump().c_str());

Desired: {"float":-0.12}
Currently: {"float":-0.12300000339746475}

@gregmarr
Copy link
Contributor

#1121

@nlohmann
Copy link
Owner

Workaround: #1191

@stale
Copy link

stale bot commented Sep 14, 2018

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the state: stale the issue has not been updated in a while and will be closed automatically soon unless it is updated label Sep 14, 2018
@stale stale bot closed this as completed Sep 21, 2018
@shubhdev
Copy link

FWIW, I feel this feature would be great as well . The workaround is a bit ugly, and I am not sure it will always work. #1121 seems to have gone stale unfortunately 😞

@lrasku
Copy link

lrasku commented Oct 17, 2018

Regarding the workaround, the old, prettier workaround described in #768 comments stopped working due to the new Grisu2 algorithm, which is selected on platforms that implement IEEE-754 floating points, i.e. almost all of them. The old workaround works if you disable the platform check, i.e. patch static constexpr bool is_ieee_single_or_double = false; in dump_float(number_float_t x).

@dvjdjvu
Copy link

dvjdjvu commented Jun 23, 2022

round((int)(val_double * 10)) / 10;
for 1 digit after ,

@gregmarr
Copy link
Contributor

@dvjdjvu That only works if that number can be represented exactly by a double. Some very surprising numbers can't, such as 0.1. It is actually stored as something like 1.00000000000000005551115123126e-1

@maddanio
Copy link

maddanio commented Jul 1, 2024

why did this get closed? I would say this is a bug, since the library simply ignores the precision setting of the stream it is writing to.

@maddanio
Copy link

maddanio commented Jul 1, 2024

I really want this to work properly (we dont need 10 places after the dot and it wastes a lot of space) and will submit a pr later

@maddanio
Copy link

maddanio commented Jul 1, 2024

stale bot closed as "completed"? wow, now we complete issues by letting them go stale :-D. anyhow, i know this is open source and we didnt pay for this, so if we want this I will implement it, l8er :)

@nlohmann
Copy link
Owner

nlohmann commented Jul 1, 2024

I would be glad to see a PR

@maddanio
Copy link

maddanio commented Jul 1, 2024

I have something working. it is not 100% backward compatible though, since for dumping to an ostream it takes the precision parameter of the ostream as a precision, which defaults to 6. now it can probably be more. I personally think 6 is enough for any realistic use case, but your mileage may vary. if you don't want to accept that then i dont know how to parameterize it for ostream dumping. well, unless you want to set it on the json itself, or you could make some fancy wrapper i.e. os << with_precision(my_json_value, n).
of course some tests fail now with this, due to the precision change, so I will hold back on the pr until a decision is reached on this. see my commit here

@t-b
Copy link
Contributor

t-b commented Jul 2, 2024

it is not 100% backward compatible though

I'm not one of developers here, but I think only 100% backwards compatible solutions will be accepted.

@maddanio
Copy link

maddanio commented Jul 2, 2024

so you think it is important to keep the 15 or so digits after the decimal points by default? Idk, I feel that very mostly it would be welcome if not so many digits are emitted. you could still do all the digits if you need by using setprecision. I think this would be a very justified "breakage", but ya, my decision. But if really wanted I can do the wrapper approach, where you would "annotate" the json while streaming.

@maddanio
Copy link

maddanio commented Jul 2, 2024

ok, ya, i can do easily: os << json::with_precision_t{myjson, prevision} syntax if that is desired. its a bit sad to ignore the precision set on the stream, as the library otherwise tries to respect stream settings like width and fill, but I will bow to the decision of the bdfl :)

@nlohmann
Copy link
Owner

nlohmann commented Jul 3, 2024

Yes, breaking changes are a no-go. That's the reason we have so many macros or other configuration options.

@maddanio
Copy link

maddanio commented Jul 3, 2024

So what can i push? The annotating wrapper and using stream precision as a switchable feature?

@maddanio
Copy link

maddanio commented Jul 3, 2024

Will go with that then and add a test, PR should be ready some time later today

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
state: stale the issue has not been updated in a while and will be closed automatically soon unless it is updated
Projects
None yet
Development

No branches or pull requests

8 participants