Recent

Author Topic: Display a double value (2^60) without rounding  (Read 3297 times)

engkin

  • Hero Member
  • *****
  • Posts: 3112
Display a double value (2^60) without rounding
« on: June 09, 2018, 11:17:01 pm »
Using FPC 3.0.4 on Win32, I expect the following code:
Code: Pascal  [Select][+][-]
  1. program project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. var
  6.   d: double;
  7. begin
  8.   d := 1152921504606846976; //2^60;
  9.   WriteLn(d:19:0);
  10.   ReadLn;
  11. end.

to give:
1152921504606846976

instead it gives:
1152921504606847000.

Is that by design?

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Display a double value (2^60) without rounding
« Reply #1 on: June 09, 2018, 11:33:05 pm »
1152921504606847000.

Is that by design?

Could be yes.  115292150460684  is 15 digits, and double has about 15-17 digits. 

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Display a double value (2^60) without rounding
« Reply #2 on: June 10, 2018, 12:02:22 am »
Could be yes.  115292150460684  is 15 digits, and double has about 15-17 digits. 
I think you are right. It seems to be a hard-coded value :(

double has about 15-17 digits. 
2^60 is a perfect double and it is 19 digits. I don't know if 15 digits is for Delphi compatibility or just an arbitrary value. The number of digits can be much bigger considering the exponent for double is 11-bit value.

On 32-bit system I can display this double value if I assign it to extended variable:
Code: Pascal  [Select][+][-]
  1. program project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. var
  6.   e: extended;
  7.   d: double;
  8. begin
  9.   d := 1152921504606846976; //2^60;
  10.   e := d;
  11.   WriteLn(e:19:0);
  12.   ReadLn;
  13. end.

rvk

  • Hero Member
  • *****
  • Posts: 6112
Re: Display a double value (2^60) without rounding
« Reply #3 on: June 10, 2018, 12:18:26 am »
2^60 is a perfect double and it is 19 digits.
So, no, 2^60 isn't a "perfect" double. It has 19 digits so it's not perfect to put into a double.

This is not only a limitation of Delphi/FPC but also exists in other languages.
Quote
A double which is usually implemented with IEEE 754 will be accurate to between 15 and 17 decimal digits. Anything past that can't be trusted, even if you can make the compiler display it.
https://stackoverflow.com/questions/11110130/double-and-accuracy

Quote
The number of digits can be much bigger considering the exponent for double is 11-bit value.
Wait, you do know double can also contain fraction of whole numbers? That's why the accuracy is only up to 15 digits. The rest of the bits are needed for encoding the fraction.

If you want whole number you should use another type (of use extended like you already mentioned).

« Last Edit: June 10, 2018, 07:18:20 am by rvk »

Blaazen

  • Hero Member
  • *****
  • Posts: 3237
  • POKE 54296,15
    • Eye-Candy Controls
Re: Display a double value (2^60) without rounding
« Reply #4 on: June 10, 2018, 01:19:40 am »
You can try:
Code: Pascal  [Select][+][-]
  1.   dec(int64(d));
  2.   WriteLn(d:19:0);
  3.   inc(int64(d));
  4.   WriteLn(d:19:0);
  5.   inc(int64(d));
  6.   WriteLn(d:19:0);
  7.  
to see that double precission can hold numbers
1152921504606846800
1152921504606847000
1152921504606847200
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

Thaddy

  • Hero Member
  • *****
  • Posts: 14213
  • Probably until I exterminate Putin.
Re: Display a double value (2^60) without rounding
« Reply #5 on: June 10, 2018, 11:23:57 am »
Only on 32 bit Windows i386 you will get the desired result:
Code: Pascal  [Select][+][-]
  1. program project1;
  2. {$mode objfpc}{$H+}
  3. var
  4.   d: extended; // <-- not double!!
  5. begin
  6.   d := 1152921504606846976; //2^60;
  7.   WriteLn(d:19:0);
  8.   ReadLn;
  9. end.[
This code relies on the FPU in the Intel family, so it is processor dependent.
On x86_64 the resolution is double (64), not extended (80).
Specialize a type, not a var.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Display a double value (2^60) without rounding
« Reply #6 on: June 10, 2018, 11:32:10 am »
2^60 is a perfect double and it is 19 digits.

The double mantissa is 52 bits. So 2^60 will have an exponent, and the compiler can't know the missing digits after  52 are 0.

The internal str (strtofloat like) procedure probably rounds the remainder after 15 digits or so, because that is all that it is sure about.

The point is the number can be altered in two places, in the literal->double and from double->string.

Gammatester

  • Jr. Member
  • **
  • Posts: 69
Re: Display a double value (2^60) without rounding
« Reply #7 on: June 10, 2018, 12:09:33 pm »
2^60 is a perfect double and it is 19 digits.
So, no, 2^60 isn't a "perfect" double. It has 19 digits so it's not perfect to put into a double.
This is not correct! Every power of two can is exactly representable as a double (up to a maximum exponent).

But as marcov has already written, a general double > 2^52 is not representable because there are only 53 mantissa bits.

PS: Even all powers of ten 10^0 .. 10^22 are exactly representable as doubles.
« Last Edit: June 10, 2018, 12:12:44 pm by Gammatester »

Gammatester

  • Jr. Member
  • **
  • Posts: 69
Re: Display a double value (2^60) without rounding
« Reply #8 on: June 11, 2018, 09:02:40 am »
2^60 will have an exponent. The compiler can't know the missing digits after 52 are 0.
And what? All IEEE double precision numbers have (biased) exponents. This is not a problem for precision, the bottleneck are the number of mantissa bits. Every (normalized) power of two has exactly zero mantissa  bits (not counting the implied bit), so every power of two is exactly representable.

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Display a double value (2^60) without rounding
« Reply #9 on: June 22, 2018, 07:28:09 am »
I blame it on Dragons!

FPC is using Grisu1* which has, beside the above mentioned limitation, a problem related to accuracy. It is possible to fall in double-rounding errors.

* About Grisu1,2 & 3: http://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf

A recent possible improvement Errol3

A widely used code comes from David Gay's dtoa.c. The author maintains the code to this day.

 

TinyPortal © 2005-2018