Bill Allombert on Mon, 11 Aug 2003 14:17:13 +0200


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

Re: Truncating real numbers


On Wed, Jul 30, 2003 at 10:38:22PM +0200, Damien Wyart wrote:
> Hello,
> 
> I need to truncate (and round) reals to keep only n digits after the
> decimal separator. This is both for display and for evaluation. I would
> like not to interact with default precision (this is quite heavy to
> change it all the time).
> 
> That is :
> 
> if a is 2.7646535646854
> 
> I both need to output a with (say) 4 digits after ., and to store this
> truncated (or rounded) number in a variable.
> 
> b = neededfunctiontrunc(a,4)
> 
> -> b now contains 2.7646
> 
> b = neededfunctionround(a,4)
> 
> -> b now contains 2.7647


Why not 
neededfunctiontrunc(x,a)=truncate(x*10^a)/10.^a
neededfunctionround(x,a)=round(x*10^a)/10.^a
?

> I looked at the function precision, but it gives strange results ; the
> behaviour doesn't seem to follow the doc ! Could someone check this ?
> 
> With default precision at startup, I get :
> 
> ? a = 2.7646535646854
> ? b = precision(a,4)
> %2 = 2.76465356
> 
> With isn't %2 2.7646 ??
> 
> Ok, I can do (notice I have to use '5' and not '4' so if the number is >
> 10, I have to ask for 6 significant digits) :
> 
> ? \p 5
> ? a
> %3 = 2.7646
> 
> But then, I have to set \p back for the next step if I want to remain
> precise enough. And a is not containing exactly the number 2.7646, it is
> only a display effect.
> 
> I am missing something ?

Probably yes. Precision in PARI is handled by full words not by digits and
stored in the objects themself. 

The 'default precision' serves (unfortunately) two purposes:
1) to decide what precision get an exact object demoted to an inexact
one:

? \p28
? sin(1+0E-28)
%1 = 0.8414709848078965066525023216
? sin(1+0E-17)
%2 = 0.8414709848078965067
? sin(1)
%3 = 0.8414709848078965066525023216
? sin(precision(1.,19))
%4 = 0.8414709848078965067

sin(x) try to compute sinus to the maximal precision available.
Since it cannot output an infinite number of digit for exact numbers
like 1, 1 is demoted to 1+0E-prec.

In the last example, precision() change the internal precision of 1.
(which is 28) to 19, so sin() only compute 19 digits. Note that
since the internal precision is in word, precision() will round up it
to the next word multiple (a word is 32*log(2)/log(10) ~ 9.63 digits).

2) to denote the numbers of digits to be printed.

Unfortunately this is the only way currently to write real numbers
with a fixed number of digits.

so you can try

neededfunctionprint(x,a)=local(p);p=default(realprecision,,1);default(realprecision,a);print(x);default(realprecision,p);

Cheers,
Bill