Json: Is there a way to control the precision of serialized floating point numbers?

Created on 4 Aug 2017  路  13Comments  路  Source: nlohmann/json

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

question proposed fix

Most helpful comment

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).

All 13 comments

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

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

Maybe by modifying the source code?

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.

Thanks, that works for my case!

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).

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.

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?

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.

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

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.

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

@CraigHutchinson Nope.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

SimplyLiz picture SimplyLiz  路  3Comments

sqwunkly picture sqwunkly  路  3Comments

moneroexamples picture moneroexamples  路  4Comments

edi9999 picture edi9999  路  3Comments

asmaloney picture asmaloney  路  4Comments