On 2020-02-26 08:20, Tobias Boege wrote:
On Wed, 26 Feb 2020, Todd Chester via perl6-users wrote:
Hi Tobias,
I am confused as to as to what you mean by numerator and
denominator.
Rational numbers can always be written as the ratio of two integers:
a/b with b non-zero. One calls a the numerator and b the denominator.
In Raku the types Int, Rat, FatRat and Num are all rational numbers,
as they all can be written as the ratio of two integers (up to Infs
and NaNs).
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?
The floating point unit in your computer receives the 2 and returns
a floating point approximation of √2. Raku then uses the algorithm
I linked to in my last email to give you the 99/70.
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?
No, Raku doesn't know anything about irrational numbers. As soon as
you obtain the return value of `sqrt(2)` in Raku, you got a rational
approximation to √2 and no part of the program knows that you wanted
to compute an irrational number. The irrationality is gone, it was
all in your head. You are dealing with this rational number that is
"close" to √2.
That is what I thought. And from an engineering standpoint,
the values used by √2 is limited by the tolerance of
the other numbers around it.
A 1.0,1.00,√2 triangle would be a tolerance of
the smaller or ±0,5, so who care how many extra digits
√2 gives me.
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?
Yes.
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?
What are you talking about? It does repeat. I suggest you take a piece
of paper and compute the decimal digits of 99/70 by hand until you are
convinced that it is 1.4 and then an endless stream of 142857 repeating.
I used gnome calculator to 20 digits:
665857/470832
1.41421356237468991063
Sorry. Not seeing any repeating patterns.
Here is NAS doing it to 1 million digits (they have too
much time on their hands):
https://apod.nasa.gov/htmltest/gifcity/sqrt2.1mil
No repeats.
So why does base-repeating tell me there is a repeating
pattern when there is not?
Ah ha, 99/70 does have a repeat:
1.4142857 142857 142857 1
Maybe 665857/470832 I just do not go out enough digits to
see a repeat.
√2 does not repeat though, but I am thinking that
I am stretching the poor machines abilities a bit too far
and that is where the repeat comes from
$ p6 'say sqrt(2).Rat.base-repeating();'
>> (1.4
14213197969543147208121827411167512690355329949238578680203045685279187817258883248730964467005076)
So, with the technology on hand, the approximation of √2
does have a repeating pattern of
14213197969543147208121827411167512690355329949238578680203045685279187817258883248730964467005076
(And in engineering terms, is meaningless)
If afterwards you trust Raku again, try `(99/70).base(10, 1000)` to get
the first thousand decimal digits of that fraction printed.
And it it can not find a repeat, why does it not say so?
If you did the pen and paper exercise above, you know how the algorithm
goes and that it is very easy to see when you've found the repeat and
when you haven't. Above, there was a repeat that was easily found.
The documentation says that if the repeat cannot be found within a
thousand digits, the repeating part in the return value of &base-repeating
will be "???".
I've found this to be false. The source code of the method does not have
such precautions and the limit is certainly not 1000 decimals. Try for
example 1/1019 which has a group of 1018 repeating decimals. [ Maybe
the number-theoretically inclined subscribers here will figure out how
I found this example. ]
Curiously, the old design docs [1] mandate a buffer of 100_000 to look
for repeating digits. Pre-christmas versions of Rakudo apparently did
have this check but "sanity", as a comment in the Rakudo sources called
it, was removed in March 2015 [2] :-)
As it currently stands [3], Rakudo will exhaust all memory to try to
find the repeating group if it has to. (Note that all rational numbers
have this repeating group -- you know this if you did the exercise --
so the search is never in vain, but it *is* attack surface for a DoS.)
And why am I getting zero back from
$ p6 'say sqrt(2).Rat.base-repeating() - (665857/470832).base-repeating();'
0
The return value of &base-repeating is a list. You are subtracting
two lists which actually gets you the difference of their lengths.
Since both lists have two elements (all lists returned by that
function do) you get zero:
> sqrt(2).Rat.base-repeating - sqrt(10000000).Rat.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?
What happens here is that the expression `665857/470832` is a
Rat literal. You take this literal Rat object and call a method
on it. It is not converted to a Num first if you meant that.
That is what I meant. I think to keep me from getting
confused, it is better for me to write (665857/470832)
as <665857/470832>, that way it is more obvious to me.
And what are the unboxing rules for (665857/470832)?
No idea what you mean.
When is <665857/470832> unboxed to a Real number to
operate on it? Or is it never unboxed?
Regards,
Tobias
[1]
https://github.com/Raku/old-design-docs/blob/180b534/S32-setting-library/Numeric.pod#base-repeating
[2] https://github.com/rakudo/rakudo/commit/418c1f33
[3]
https://github.com/rakudo/rakudo/blob/3e332a1/src/core.c/Rational.pm6#L351-L369
Hopefully, I think I have it now. Thank you!