Re: why so different

2020-06-22 Thread Aureliano Guedes
Thanks again.

I'm trying to get proficiency in Raku by converting some Python programs
mine in Raku.

On Mon, Jun 22, 2020 at 6:41 PM Tobias Boege  wrote:

> On Mon, 22 Jun 2020, Aureliano Guedes wrote:
> > Thank you for the clarification.
> >
> > There is a method to set Rat precision at the scope of the program to
> apply
> > to all *.Rat() cases?
> >
>
> I don't know, based on a quick search in the documentation, of any global
> setting. The hacky solution would be to wrap the method like this:
>
>   say pi.Rat.nude;  # OUTPUT: (355 113)
>
>   Num.^find_method('Rat').wrap: -> |c {
>   # Make the default argument 1e-20
>   callwith |(|c, 1e-20 if c.elems ≤ 1)
>   };
>
>   say pi.Rat.nude;  # OUTPUT: (245850922 78256779)
>
> This program has three parts. First, we print pi.Rat.nude for comparison.
> The nude method returns numerator and denominator of a Rat as a list.
> The last part is just looking at pi.Rat.nude again to confirm that the
> change in the middle has worked and increased the default precision.
>
> You said you are relatively new to Raku, so let me explain the middle part.
> Raku has a special syntax for calling metamethods (i.e. doing
> introspection)
> on an object or type, which is the .^ operator. I use it to access an
> object
> representation of the Rat method on the Num type. I can wrap some code of
> my liking around this method via its wrap method.
>
> The `-> |c { … }` syntax creates an anonymous code block that wraps around
> the Num.Rat method and it accepts all arguments that may be passed as a
> Capture [1] in the variable c. If that Capture does not have a first
> parameter, i.e. the precision is not specified, I sneak in my 1e-20.
> Afterwards, the `callwith |(…)` part unpacks the (modified) captured
> arguments and calls the original method that I am wrapping [2].
>
> Effectively, I pass a precision of 1e-20 whenever the caller did not pass
> a precision. You can see that the wrapping takes effect immediately in
> the last line of the above program.
>
> Ideally, this could be turned into a module that hides the questionable
> means behind a dynamic $*RAT-PRECISION variable or so. That is, unless
> someone comes up with an even better solution.
>
> Best,
> Tobias
>
> [1] https://docs.raku.org/type/Capture
> [2] https://docs.raku.org/routine/wrap
>
> --
> "There's an old saying: Don't change anything... ever!" -- Mr. Monk
>


-- 
Aureliano Guedes
skype: aureliano.guedes
contato:  (11) 94292-6110
whatsapp +5511942926110


Re: why so different

2020-06-22 Thread Tobias Boege
On Mon, 22 Jun 2020, Aureliano Guedes wrote:
> Thank you for the clarification.
> 
> There is a method to set Rat precision at the scope of the program to apply
> to all *.Rat() cases?
> 

I don't know, based on a quick search in the documentation, of any global
setting. The hacky solution would be to wrap the method like this:

  say pi.Rat.nude;  # OUTPUT: (355 113)

  Num.^find_method('Rat').wrap: -> |c {
  # Make the default argument 1e-20
  callwith |(|c, 1e-20 if c.elems ≤ 1)
  };

  say pi.Rat.nude;  # OUTPUT: (245850922 78256779)

This program has three parts. First, we print pi.Rat.nude for comparison.
The nude method returns numerator and denominator of a Rat as a list.
The last part is just looking at pi.Rat.nude again to confirm that the
change in the middle has worked and increased the default precision.

You said you are relatively new to Raku, so let me explain the middle part.
Raku has a special syntax for calling metamethods (i.e. doing introspection)
on an object or type, which is the .^ operator. I use it to access an object
representation of the Rat method on the Num type. I can wrap some code of
my liking around this method via its wrap method.

The `-> |c { … }` syntax creates an anonymous code block that wraps around
the Num.Rat method and it accepts all arguments that may be passed as a
Capture [1] in the variable c. If that Capture does not have a first
parameter, i.e. the precision is not specified, I sneak in my 1e-20.
Afterwards, the `callwith |(…)` part unpacks the (modified) captured
arguments and calls the original method that I am wrapping [2].

Effectively, I pass a precision of 1e-20 whenever the caller did not pass
a precision. You can see that the wrapping takes effect immediately in
the last line of the above program.

Ideally, this could be turned into a module that hides the questionable
means behind a dynamic $*RAT-PRECISION variable or so. That is, unless
someone comes up with an even better solution.

Best,
Tobias

[1] https://docs.raku.org/type/Capture
[2] https://docs.raku.org/routine/wrap

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: why so different

2020-06-22 Thread Aureliano Guedes
Thank you for the clarification.

There is a method to set Rat precision at the scope of the program to apply
to all *.Rat() cases?



On Mon, Jun 22, 2020 at 5:57 PM Tobias Boege  wrote:

> On Mon, 22 Jun 2020, Aureliano Guedes wrote:
> > Hi all,
> >
> > First, I'm naive in Raku. Then let's go to my question.
> >
> > I'm trying to figure out why we got so different results here:
> >
> > > e.Rat()**(pi.Rat()*i)
> > -0.9902-1.3942922582021257e-07i
> > > e**(pi*i)
> > -1+1.2246467991473532e-16i
> > > e.Rat()**(pi.Rat()*i) == e**(pi*i)
> > False
> >
> > I understand the Num actually have the traditional behavior which leads
> > this:
> > 0.1.Num() + 0.2.Num() != 0.3.Num()
> >
> > And Rat is awesome cos deal nice to the real world.
> >
> > Anyway, I do not expect so different results between Rat and Num.
> >
>
> First, e and π are not rational numbers, so Num (IEEE 754 double)
> and Rat (pair of bigint numerator and denominator) both will be only
> approximations.
>
> The literals e and pi in Raku are typed as Num and when you call the
> Rat method on them, you get a Rat back with the *default* precision
> of 1e-6 [1]. That is a lot less precise than the Nums you started
> with, hence the difference. Try supplying a large enough precision:
>
>   > e.Rat(1e-200)**(pi.Rat(1e-200)*i)
>   -1+1.2246467991473532e-16i
>
> This is better than a default .Rat() but notice that you cannot get
> past the limited precision in the source Nums, which is ca. 1e-16.
>
> Best,
> Tobias
>
> [1] https://docs.raku.org/routine/Rat
>
> --
> "There's an old saying: Don't change anything... ever!" -- Mr. Monk
>


-- 
Aureliano Guedes
skype: aureliano.guedes
contato:  (11) 94292-6110
whatsapp +5511942926110


Re: why so different

2020-06-22 Thread Tobias Boege
On Mon, 22 Jun 2020, Aureliano Guedes wrote:
> Hi all,
> 
> First, I'm naive in Raku. Then let's go to my question.
> 
> I'm trying to figure out why we got so different results here:
> 
> > e.Rat()**(pi.Rat()*i)
> -0.9902-1.3942922582021257e-07i
> > e**(pi*i)
> -1+1.2246467991473532e-16i
> > e.Rat()**(pi.Rat()*i) == e**(pi*i)
> False
> 
> I understand the Num actually have the traditional behavior which leads
> this:
> 0.1.Num() + 0.2.Num() != 0.3.Num()
> 
> And Rat is awesome cos deal nice to the real world.
> 
> Anyway, I do not expect so different results between Rat and Num.
> 

First, e and π are not rational numbers, so Num (IEEE 754 double)
and Rat (pair of bigint numerator and denominator) both will be only
approximations.

The literals e and pi in Raku are typed as Num and when you call the
Rat method on them, you get a Rat back with the *default* precision
of 1e-6 [1]. That is a lot less precise than the Nums you started
with, hence the difference. Try supplying a large enough precision:

  > e.Rat(1e-200)**(pi.Rat(1e-200)*i)
  -1+1.2246467991473532e-16i

This is better than a default .Rat() but notice that you cannot get
past the limited precision in the source Nums, which is ca. 1e-16.

Best,
Tobias

[1] https://docs.raku.org/routine/Rat

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk