> 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)