#1 2015-10-08 08:15:19

Dmitro25
Member
Registered: 2015-02-21
Posts: 19

Precision of conversion float types to text in JSON is insufficient

Hi.
I use "Single" type to store numbers in JSON. I recently discovered that in the conversion of such numbers to the text form precision is lost (if to convert the resulting text back to a number, the result is differ from the initial).
Example:

var
  v1, v2: Single;
  i: integer;
  s: string;
begin
  i := $C120000B;
  v1 := pSingle(@i)^;
  s := SynCommons.ExtendedToStr(v1, SINGLE_PRECISION{ + 1});
  v2 := StrToFloat(s);
  if v1 <> v2 then
    raise Exception.Create('Differ!');
end;

And those numbers enough numerous.
The solution is proposed here https://randomascii.wordpress.com/2012/ … -digits-2/
I propose to increase the SINGLE_PRECISION constant from 8 to 9 (I've checked, this fixes the inaccuracy). Maybe DOUBLE_PRECISION should also be increased to 17, as indicated in the article.

Last edited by Dmitro25 (2015-10-08 08:16:36)

Offline

#2 2015-10-08 09:52:50

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: Precision of conversion float types to text in JSON is insufficient

AFAIK we followed Delphi usual precision...

Official Delphi Documentatoin wrote:

The Precision parameter specifies the precision of the given value. It should be 7 or less for values of type Single, 15 or less for values of type Double, and 18 or less for values of type Extended.

See http://docwiki.embarcadero.com/Librarie … loatToStrF


IF we increase DOUBLE_PRECISION to 16 we get unexpected results like:

  d := 9.999999999999997;
  a[0] := AnsiChar(ExtendedToString(a,d,DOUBLE_PRECISION));
  // here a='9.999999999999996, but we expected '9.999999999999997'

So I'm not convinced it is safe to increase the constants.

Online

#3 2015-10-08 11:53:35

Dmitro25
Member
Registered: 2015-02-21
Posts: 19

Re: Precision of conversion float types to text in JSON is insufficient

ab
Your example contain an implicit assumption that number "9.999999999999997" can be converted to "double" type without error. But it's not. The compiler assigns to variable a value about "9.99999999999999645", so "9.999999999999996" is the best approach for it than "9.999999999999997".
You can check it with the following example:

var
  v1, v2: double;
  s: string;
begin
  v1 := 9.999999999999997;
  s := ExtendedToStr(v1, DOUBLE_PRECISION); // DOUBLE_PRECISION=15
  v2 := StrToFloat(s);
  if v1 <> v2 then
    ShowMessage('Differ1');
  s := ExtendedToStr(v1, DOUBLE_PRECISION + 1);
  v2 := StrToFloat(s);
  if v1 <> v2 then
    ShowMessage('Differ2');
end;

You will see only "Differ1" message.

Offline

#4 2015-10-08 12:10:50

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: Precision of conversion float types to text in JSON is insufficient

You are using StrToFloat() which convert the string to an extented 80 bit variable, so your conversion is not symmetric.
My test case was symmetric, since it compared the string value.

I doubt Delphi RTL experts (back in Borland time), did not set the appropriate precisions for the RTL, and that it was never changed after more than 20 years.
AFAIK .Net runtime made the same assumption when converting a double to text - http://stackoverflow.com/a/1664351/458259

An IEEE double has 53 significant bits (that's the value of DBL_MANT_DIG in <cfloat>). That's approximately 15.95 decimal digits (log10(253)); the implementation sets DBL_DIG to 15, not 16, because it has to round down. So you have nearly an extra decimal digit of precision (beyond what's implied by DBL_DIG==15) because of that.

I guess the reason is explained here http://stackoverflow.com/a/9999374/458259

If you have a number with 15 decimal places and convert that to a double, then print it out with exactly 15 decimal places, you should get the same number. On the other hand, if you print out an arbitrary double with 15 decimal places and the convert it back to a double, you won't necessarily get the same value back—you need 17 decimal places for that. And neither 15 nor 17 decimal places are enough to accurately display the exact decimal equivalent of an arbitrary double. In general, you need over 100 decimal places to do that precisely.

Online

#5 2015-10-08 13:24:27

Dmitro25
Member
Registered: 2015-02-21
Posts: 19

Re: Precision of conversion float types to text in JSON is insufficient

You believe that a reference value for computing floating point is a string. I think that the number (binary representation) is more important. Let me explain my position. I plan to store in the database a set of coordinates in JSON format. Initially the coordinates are numbers ("Single" type). The user should be able to change the coordinates of individual points, leaving the rest unchanged. As a result of coordinate will periodically be converted from JSON (text) to numeric form and Vice versa. I am afraid that as a result of errors discussed above after multiple conversions coordinates will started to "drift" each time the user edits the data.
With increased accuracy data can be easy converted multiple times without loss of information.

Offline

#6 2015-10-08 14:06:30

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: Precision of conversion float types to text in JSON is insufficient

My concern is that in some cases, the text output may be filled with garbage, due to too big precision.

Online

#7 2015-10-08 15:15:51

Dmitro25
Member
Registered: 2015-02-21
Posts: 19

Re: Precision of conversion float types to text in JSON is insufficient

I understand. Some time ago, at my request, you have added a "Single" type support when creating JSON (thank you). May be there is some way to make precision customizable without breaking the code optimization. May be to make SINGLE_PRECISION and DOUBLE_PRECISION not a constants but a variables or to provide some another interface to this values. I think, other people too may encounter the same problem, not just me.

Offline

#8 2015-10-09 06:09:04

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: Precision of conversion float types to text in JSON is insufficient

See http://synopse.info/fossil/info/aa9734958d

Thanks for the feedback!

Online

#9 2015-10-09 06:18:49

Dmitro25
Member
Registered: 2015-02-21
Posts: 19

Re: Precision of conversion float types to text in JSON is insufficient

Thank you

Offline

#10 2015-10-09 07:47:54

Dmitro25
Member
Registered: 2015-02-21
Posts: 19

Re: Precision of conversion float types to text in JSON is insufficient

I've checked for "Single" type and precision=8. Difference between values before ExtendedToStr and after StrToFloat is not exceed 1LSB and have no trends to "drift".

Offline

Board footer

Powered by FluxBB