On 2020-02-20 22:32, Tobias Boege wrote:
On Thu, 20 Feb 2020, ToddAndMargo via perl6-users wrote:
On Fri, 21 Feb 2020 at 13:31, ToddAndMargo via perl6-users
<perl6-us...@perl.org <mailto:perl6-us...@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


Hi Tobias,

I am confused as to as to what you mean by numerator and
denominator.

When I say:
$ p6 'say (99/70).base-repeating();'
(1.4 142857)

$ p6 'say (665857/470832).base-repeating();'
(1.4142 135623746899106262955788901349101165596221157440445849050192000543718353892683589900431576443402317599483467563801950589594590002378767798280490705814388146939885139497740170591633533829476331260407109117477146837937948142861997485302613246338396710503958949264281102388962517415978523125021238998198932952730485608454820403031229822951711013694906038671967920617120331668195874536989839263261630475413735684915213919189859652699901451048356951099330546776769633329935093621504060896455635980562068848336561661059571142148367145818466034594080266421993407414959051211472457267)

$ p6 'say sqrt(2).Rat.base-repeating();'
(1.4 14213197969543147208121827411167512690355329949238578680203045685279187817258883248730964467005076)

How does Raku know √2 is approximated by 99/70 or 665857/470832?
Does not Raku just throw a binary algorithm at any number you
feed sqrt?

also, what exactly am I look at with (1.4 142857)?   Is
this a way of saying that 1.4 is the rational part and
142857 the irrational part?

What is also confusing is when a number does not repeat,
what is .base-repeating() trying to tell me?  Is does not repeat?

2/3 is 0.6666666.
$ p6 'say (2/3).Rat.base-repeating();'
(0. 6)

Does that mean that the 6 repeats?

and

$ p6 'say (99/70).base-repeating();'
(1.4 142857)

means that 142857 also repeats (it does not), but
that it is best it can figure out with the precision
it has?

And it it can not find a repeat, why does it not say so?

And why am I getting zero back from
$ p6 'say sqrt(2).Rat.base-repeating() - (665857/470832).base-repeating();'
0

Also, what is the algebraic precedence of the operation?  In
    (665857/470832).base-repeating()

is (665857/470832) solved first or is (665857/470832) a special
number (Rat) that is fed to .base-repeating?

And what are the unboxing rules for (665857/470832)?

Yours in confusion,
-T

Reply via email to