> On Oct 31, 2021, at 6:10 AM, ToddAndMargo via perl6-users 
> <perl6-us...@perl.org> wrote:
> 
> On 10/31/21 01:43, Shlomi Fish wrote:
> 
>>> ("" ~ sqrt(2)).comb().grep(* ne ".").map(+*)
>> (1 4 1 4 2 1 3 5 6 2 3 7 3 0 9 5 1)
> 
> Cool!
> 
> my Int @x = ("" ~ sqrt(2)).comb().grep(* ne ".").map(+*)
> [1 4 1 4 2 1 3 5 6 2 3 7 3 0 9 5 1]
> 
> Is there a way to set how many digits I get?


[
        Aside: This aspect is underspecified: "how many digits"; do you want to 
specify the total digits, or digits-after-decimal-point?
                sqrt(333) = 18.24828759089466...
        If you say:
                my $wanted_digits = 5;
        , which of these are you wanting:
                1824828
                18248
        ?
]

Like most languages, the "precision" (number of digits actually generated) for 
functions like sqrt() and sin() is fine-tuned to the "size" of Raku's floating 
point numbers (Num).
So:
    1. You cannot set Raku to produce only 3 decimal places. You *can* receive 
all the digits, then trim them down yourself.
    2. You cannot set Raku to produce more decimal places than it currently 
generates. You *can* use your own code to generate unlimited decimal places for 
most FP functions.

Examples:
# 1
my $wanted_digits = 15;
my Int @x = (sqrt(2) * (10**$wanted_digits)).floor.comb.map(+*);        # Will 
have incorrect digits at end, if $wanted_digits > 15.
my Int @x = sqrt(2).comb.grep(* ne ".").head($wanted_digits).map(+*);   # Will 
not produce over 17 digits for sqrt2, even if $wanted_digits is much higher, 
and the 17th digit is incorrect.

sqrt(333)
    18.24828759089466
my $wanted_digits = 10;
my Int @x = (sqrt(333) * (10**$wanted_digits)).floor.comb.map(+*);
    [1 8 2 4 8 2 8 7 5 9 0 8]
my Int @x = sqrt(333).comb.grep(* ne ".").head($wanted_digits).map(+*);
    [1 8 2 4 8 2 8 7 5 9]

# 2
Use http://rosettacode.org/wiki/Integer_roots#Raku , which will accurately 
produce absurdly large digits counts for [square|cube|any-integer] roots.
The code is my own translation from Python (which looks like it was based on 
https://en.wikipedia.org/wiki/Nth_root#Computing_principal_roots ), so I can 
answer questions on it.

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 };
    return (+$guess, $iterator ... $endpoint).tail(2).min;
}
my $wanted_digits = 30;
say integer_root( 2, 333 * 100 ** $wanted_digits 
).comb.head($wanted_digits).map(+*);
    (1 8 2 4 8 2 8 7 5 9 0 8 9 4 6 5 9 0 6 6 9 9 9 0 5 2 7 3 5 6)


Afterthought:
Re-reading the thread and OP, I see that you might simply need to add the 
.head() method to the end of other (already kindly provided) code.
If you already have created the array, and it might be too long, you can do 
this as a separate statement:
        @y .= head($wanted_size);
If you truly are trying to limit the number of decimal places (as opposed to 
total array length), then you can factor in the size of the integer part, with 
something like this (only lightly tested) code:
        @y .= head($wanted_decimal_places + $original_number.sqrt.floor.chars);

-- 
Hope this helps,
Bruce Gray (Util of PerlMonks)

Reply via email to