On Thu, 20 Feb 2020, ToddAndMargo via perl6-users wrote:
> > > On Fri, 21 Feb 2020 at 13:31, ToddAndMargo via perl6-users
> > > <perl6-users@perl.org <mailto:perl6-users@perl.org>> wrote:
> > > 
> > >     $ perl6 -e 'say sqrt(2).base-repeating();'
> > >     No such method 'base-repeating' for invocant of type 'Num'
> > >         in block <unit> at -e line 1
> > > 
> 
> On 2020-02-20 19:07, Norman Gaywood wrote:
> > 
> > perl6 -e 'say sqrt(2).Rat.base-repeating();'
> > (1.4 
> > 14213197969543147208121827411167512690355329949238578680203045685279187817258883248730964467005076)
> 
> Hi Norman,
> 
> Much better!
> 
> Question: Rat:
> https://docs.raku.org/type/Rat
> 
>       Rat objects store rational numbers as a pair
>       of a numerator and denominator. Number literals
>       with a dot but without exponent produce Rats.
> 
> What does Rat do to sqrt(2) to give it a numerator
> and a denominator?
> 

I'm not sure if you have digested what others have said, so I'll repeat it:
sqrt(2) already has a numerator and denominator. sqrt(2) takes the integer
2 and computes its square root as a floating point number using magic IEEE
powder. If you look up the IEEE 754 float representations, you'll notice
that every (non-NaN, non-Inf) float is a rational number. So sqrt(2) is
already a rational number approximating the positive real number whose
square is 2.

That said, just taking the obvious numerator and denominator from the float
might give you unnecessarily large numbers, and the Rat conversion on Num
has to support a user-supplied tolerance as well. Reading the documentation,
it seems that Raku does not require IEEE 754 to be in effect at all.

So what Rakudo does (I recommend reading the source code [1]) is a variant
of finding a continued fraction for the Num [2], except that it computes
the Rat instead and stops when it reached the requested accuracy. It starts
from scratch and iteratively approximates the Num, which has the advantage
that you can stop when you don't have to continue and that it only relies
on arithmetic on the Num working, not that it is represented according to
some standard internally.

Note also that Num.Rat supports a :fat argument to give you a FatRat back,
but you cannot actually increase the precision of your rational approximation
of √2 beyond the source you put in, which is a double precision float:

  > sqrt(2).Rat.nude         # precision 1e-6, the default
  (1393 985)
  > sqrt(2).Rat(1e-8).nude   # a bit better requested, request granted
  (19601 13860)
  > sqrt(2).Rat(1e-16).nude  # still better but 1e-16 is ca. the limit
  (131836323 93222358)

  > sqrt(2).Rat(1e-20).nude  # no improvement
  (131836323 93222358)
  > sqrt(2).Rat(1e-100, :fat).nude  # fatter but not better, because
  (131836323 93222358)              # the source sqrt(2) is too lossy

Regards,
Tobias

[1] https://github.com/rakudo/rakudo/blob/cdbd60c1/src/core.c/Num.pm6#L46
[2] 
https://en.wikipedia.org/wiki/Continued_fraction#Calculating_continued_fraction_representations

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk

Reply via email to