Thread overview
Value of floating in JSONValue
Aug 21, 2014
nrgyzer
Aug 21, 2014
Ali Çehreli
Aug 21, 2014
Idan Arye
Aug 22, 2014
nrgyzer
Aug 22, 2014
Nobody
August 21, 2014
Hi everyone,

I'm facing a problem with the JSON functions. I've to communicate
with another PC using JSON. Here's a simple snipped which shows
my problem:

import std.json;
import std.stdio;
void main()
{
	double d = 1.23456789;
	JSONValue j = d;
	sendToRemote(toJSON(&j));
}

My problem is that the remote PC receives 1.23457 instead of
1.23456789. But when I add the following:

import std.json;
import std.stdio;
void main()
{
	double d = 1.23456789;
	JSONValue j = d;
	sendToRemote(toJSON(&j));
	writefln("%.8f", j.floating);
}

writefln() shows me 1.23456789. So, the value is correct. I think
the problem is the default representation of any floating point
number to string. Is there any chance I can send 1.23456789
instead of 1.23457 to my remote PC?

Note: I cannot use strings because the other PC expects a numeric
data type.
August 21, 2014
On 08/21/2014 11:53 AM, nrgyzer wrote:

>      double d = 1.23456789;
>      JSONValue j = d;
>      sendToRemote(toJSON(&j));
> }
>
> My problem is that the remote PC receives 1.23457 instead of
> 1.23456789.

I think it is due to the following code simply calling to!string in std/phobos/json.d:

            case JSON_TYPE.FLOAT:
                json.put(to!string(value.store.floating));
                break;

> But when I add the following:
>
> import std.json;
> import std.stdio;
> void main()
> {
>      double d = 1.23456789;
>      JSONValue j = d;
>      sendToRemote(toJSON(&j));
>      writefln("%.8f", j.floating);
> }
>
> writefln() shows me 1.23456789. So, the value is correct.

It is more precise but still not correct because that specific double value cannot be represented exactly.

> Is there any chance I can send 1.23456789
> instead of 1.23457 to my remote PC?

You can call a function like the following:

import std.string;
import std.json;
import std.stdio;

string morePrecisely(double d)
{
    return format("%.20g", d);
}

void main()
{
    double d = 1.23456789;
    JSONValue root = [ "value" : d.morePrecisely ];
    writeln(toJSON(&root));
}

Of course do something more sensible than hard-coding the 20 in that format string. :)

> Note: I cannot use strings because the other PC expects a numeric
> data type.

I don't think it is a concern as JSON does not encode types. It is up to the receiver how to interpret the data. Here is the output of the program above:

{"value":"1.2345678899999998901"}

Ali

August 21, 2014
On Thursday, 21 August 2014 at 23:05:48 UTC, Ali Çehreli wrote:
> I don't think it is a concern as JSON does not encode types. It is up to the receiver how to interpret the data. Here is the output of the program above:
>
> {"value":"1.2345678899999998901"}
>
> Ali

JSON may not encode the very specific type the language that created it was using, but it does differ between strings and numbers. {"value":"1.2345678899999998901"} is different from {"value":1.2345678899999998901}, virtually any JSON implementation for any language(there might be exceptions - maybe TCL) will parse them to different language constructs, and code that expect one may fail, crash or misbehave when given the other.
August 22, 2014
On Thursday, 21 August 2014 at 23:29:56 UTC, Idan Arye wrote:
> On Thursday, 21 August 2014 at 23:05:48 UTC, Ali Çehreli wrote:
>> I don't think it is a concern as JSON does not encode types. It is up to the receiver how to interpret the data. Here is the output of the program above:
>>
>> {"value":"1.2345678899999998901"}
>>
>> Ali
>
> JSON may not encode the very specific type the language that created it was using, but it does differ between strings and numbers. {"value":"1.2345678899999998901"} is different from {"value":1.2345678899999998901}, virtually any JSON implementation for any language(there might be exceptions - maybe TCL) will parse them to different language constructs, and code that expect one may fail, crash or misbehave when given the other.

That's exactly my problem. The remote PC expects a numeric value
with a precision of up to 6 floating points. So using a string
instead of float would cause an error.
August 22, 2014
On Thursday, 21 August 2014 at 18:53:08 UTC, nrgyzer wrote:
> Hi everyone,
>
> I'm facing a problem with the JSON functions. I've to communicate
> with another PC using JSON. Here's a simple snipped which shows
> my problem:
>
> import std.json;
> import std.stdio;
> void main()
> {
> 	double d = 1.23456789;
> 	JSONValue j = d;
> 	sendToRemote(toJSON(&j));
> }
>
> My problem is that the remote PC receives 1.23457 instead of
> 1.23456789. But when I add the following:
>
> import std.json;
> import std.stdio;
> void main()
> {
> 	double d = 1.23456789;
> 	JSONValue j = d;
> 	sendToRemote(toJSON(&j));
> 	writefln("%.8f", j.floating);
> }
>
> writefln() shows me 1.23456789. So, the value is correct. I think
> the problem is the default representation of any floating point
> number to string. Is there any chance I can send 1.23456789
> instead of 1.23457 to my remote PC?
>
> Note: I cannot use strings because the other PC expects a numeric
> data type.

Hi, my answer will be a bit OT, and is not really an answer but:

FP precision matters "only" during processing. I don't know which is the context but for example if it represents a parameter you could try
- to encode it to a fraction representation like "1/3".
- to encode it to a fixed-point float value.
- mapping the value in the range of -1.0 to 1.0 because by nature, FP values are more accurate in this range.
- to use a more accurate type: send a double (more precision), reduce it to a float (your 6 decimals are then granted).

Note 1: still about the context, remember that this is a damn small delta. Does this delta is that much a concern ?

Note 2: singles (we speak about IEEE 754, 32bits right ?) are not always 6 decimals precision, it's 5 >>OR<< 6.