On 2020-05-15 12:09, Bruce Gray wrote:


On May 14, 2020, at 4:36 PM, ToddAndMargo via perl6-users 
<perl6-us...@perl.org> wrote:

On 2020-05-14 08:13, Bruce Gray wrote:
On May 14, 2020, at 7:27 AM, ToddAndMargo via perl6-users 
<perl6-us...@perl.org> wrote:

Hi All,

1) how do I get 40 or more digits out of sqrt?
—snip—
Use an Integer Root algorithm on ($number-you-want-the-root-of * 100 ** 
$number-of-digits-you-want), then shift the decimal point of the result.
Exact code here:
        https://rosettacode.org/wiki/Integer_roots#Raku
—
Hope this helps,
Bruce Gray (“Util” on RosettaCode, too)


sub integer_root ( Int $p where * >= 2, Int $n --> Int ) {
    my Int $d = $p - 1;
    my $guess = 10**($n.chars div $p);
    my $iterator = { ( $d * $^x   +   $n div ($^x ** $d) ) div $p };
    my $endpoint = {      $^x      ** $p <= $n
                     and ($^x + 1) ** $p >  $n };
    min (+$guess, $iterator ... $endpoint)[*-1, *-2];
}

say integer_root( 2, 2 * 100 ** 2000 );



It does help!  I can reproduce noise to my heart's content!

Hmmmm. See my `srand` note at the end.


Questions:

what is $p in the sub declaration? Is it always a 2?

$p is the “degree” of the root wanted; 2 for square root, 3 for cube root, etc.


what is `$n` in the sub declaration?

$n is the number that you want the root of.

Looks like
the third set of numbers is the digits I want.

what is the second number (100)?

100 is (10 ** $degree), and the degree is `2` for square root.


And what is `2 * 100 ** 2000 `?  Is that `(2 x 100)^ 2000`
((2 times 100) to the 2000 power?

As Peter Pentchev pointed out, A * B ** C is always interpreted as A * (B ** C).


say integer_root( 2, 2 * 100 ** 4 );
14142

say 3.sqrt
1.7320508075688772

say integer_root( 2, 3 * 100 ** 16 );
17320508075688772


-T


I see from your question that while the RosettaCode solution is generally clear 
for the task itself, the use of `100` in the calling code is less clear. (I 
will fix that on RC)

An "integer root" algorithm, taken by itself, only gives you a fast/direct 
method to find `($number ** (1/$root_wanted)).floor` without ever using floating point.
To use such an algorithm to produce more digits, we have to *scale* the number 
such that the root of the scaling factor is a power of 10, so the scaling 
factor must be a power of (10 ** $root_wanted).
For square roots, we need (10 ** 2), which is why the RC code says `100`; the 
square root of 100 is 10, and `10` slides the decimal point while preserving 
the digits.
        $ perl6 -e 'say .sqrt.floor for 2, 200, 20000, 2000000, 200000000'
        1
        14
        141
        1414
        14142


So, the "root wanted" (like 2 for square root, 3 for cube root, etc) occurs 
twice in the integer_root() call; once as the first argument `p`, and again in the 
exponent of 10 in the multiplier for the second argument.
e.g. to get the first 42 digits of the cube root of 88:
        say integer_root( 3, 88 * ((10 ** 3) ** 42) );
        4447960181138631042330726753444314393037398

Or:
        sub lots_of_digits_of_root ( $radicand, $degree, $extra_digit_count ) {
                return integer_root( $degree, $radicand * ((10 ** $degree) ** 
$extra_digit_count) );
        }
        say lots_of_digits_of_root( 88, 3, 42 );
        4447960181138631042330726753444314393037398

Finally, you said "reproduce noise", which makes me think that you might be 
going down this sqrt(2)-road from having tried Raku's rand() for noise, but hitting the 
problem of its non-reproducibility.
If so, a much simpler method would be to use the built-in solution: Call 
`srand` to force `rand` to use a some fixed starting-point.
        # All different:
        $ perl6 -e '           say (^10).roll(*).head(15);' # (5 5 7 9 8 7 6 9 
1 2 1 3 3 0 6)
        $ perl6 -e '           say (^10).roll(*).head(15);' # (2 7 3 4 3 9 9 3 
2 2 4 6 5 9 9)
        $ perl6 -e '           say (^10).roll(*).head(15);' # (2 2 1 7 1 7 6 3 
1 2 4 1 3 1 4)
        $ perl6 -e '           say (^10).roll(*).head(15);' # (4 7 1 0 8 5 6 6 
0 1 8 2 3 3 6)
        # All identical
        $ perl6 -e 'srand(42); say (^10).roll(*).head(15);' # (4 3 9 3 6 1 1 0 
0 5 8 3 6 7 0)
        $ perl6 -e 'srand(42); say (^10).roll(*).head(15);' # (4 3 9 3 6 1 1 0 
0 5 8 3 6 7 0)
        $ perl6 -e 'srand(42); say (^10).roll(*).head(15);' # (4 3 9 3 6 1 1 0 
0 5 8 3 6 7 0)
        $ perl6 -e 'srand(42); say (^10).roll(*).head(15);' # (4 3 9 3 6 1 1 0 
0 5 8 3 6 7 0)

—
HTH, Util
Harry knew pi to 3.141592 because accuracy to one part in a million was enough 
for most practical purposes.
Hermione knew one hundred digits of pi because that was how many digits had 
been printed in the back of her maths textbook.
https://www.hpmor.com/chapter/9



Thank you!!!

Reply via email to