Ruud H.G. van Tol on Sun, 15 Dec 2024 13:15:47 +0100


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: digits of a float



On 2024-12-15 12:31, Bill Allombert wrote:
On Sat, Dec 14, 2024 at 12:07:29PM +0100, Ruud H.G. van Tol wrote:
How to properly isolate a digit of a float?

Example:

? my(n=19437); localprec(n+2); Pi *10^(n-1) \1 %10
%4 = 7

? my(n=19437); localprec(n+3); Pi *10^(n-1) \1 %10
%5 = 6

That type of code depends on the number of 9-digits in the decimal expansion
of the value.

See also https://oeis.org/A000796, which uses localprec(n*6\5+29).

What clean ways are there?
This is difficult. One need to round toward 0 instead of rounding to nearest
as usual.

In this instance the number end by 574699992... which is (correctly) rounded to nearest
by PARI to 5747.....

I wrote this, which increase the accuracy until there is no more ambiguity.
{
   my(n=19437,z);
   for(m=n+1,oo,
     localprec(m+1);
     z = round(Pi *10^m)/10^m;
     if(abs(z-Pi)>10^-(m+1),break));
   z*10^(n-1)\1%10
}

but this need to be checked more carefully

Yes, I have used something similar. Also for non-Pi-cases.


Bigger steps are feasible:

? my(r=List(), p=0); for(i=1, 10, localprec(p+1); listput(~r, p=precision(.))); Vec(r)
% [19, 38, 57, 77, 96, 115, 134, 154, 173, 192]


Specifically for Pi, I noticed that 4*atan(1) has a higher precision than default:
? localprec(1); [ precision(.), precision(Pi), precision(4*atan(1)) ]
% [19, 19, 38]


The "precision" mentioned in the printf-docs is yet another type of precision: ? localprec(1); my(v=1-10^-40); strprintf("%s | %s | %.*f", precision(.), 1.-v, 28, v*1.)
% "19 | 0.E-18 | 0.9999999999999999999731564544"

-- Ruud