Re: (default) Real->Rat precision should match what compiler uses for literals

2018-03-03 Thread Brandon Allbery
Max precision rapidly becomes more memory requires than your computer has.

On Sat, Mar 3, 2018 at 3:32 PM, yary  wrote:

> Or instead of 1/2**(32 or 64), re-asking these questions about epsilon:
>
> "  Why so large?
>
>Why not zero?  "
>
> What's justification for using 1/100,000 vs. something smaller vs. 0 "max
> possible precision?"
>



-- 
brandon s allbery kf8nh   sine nomine associates
allber...@gmail.com  ballb...@sinenomine.net
unix, openafs, kerberos, infrastructure, xmonadhttp://sinenomine.net


Re: (default) Real->Rat precision should match what compiler uses for literals

2018-03-03 Thread yary
Still thinking this out. Does the default epsilon influence a Rat == Float
comparison? If so, for that purpose, the most useful epsilon is one that
maximizes its correctness.


Re: (default) Real->Rat precision should match what compiler uses for literals

2018-03-03 Thread yary
Or instead of 1/2**(32 or 64), re-asking these questions about epsilon:

"  Why so large?

   Why not zero?  "

What's justification for using 1/100,000 vs. something smaller vs. 0 "max
possible precision?"


Re: (default) Real->Rat precision should match what compiler uses for literals

2018-03-03 Thread yary
Zeroing in on one point:

> > A solution might be to instead provide a pragmatic, rather than
> mathematical
> > parameter:
> >
> > :$numbits = 64
> >
> > This would say to keep as much precision as possible while making the
> result
> > fit in 64 bits.   For example 2.147483647e0.Rat would result in
> > 2147483647/10 instead of 4310/2007.
>
> The Num type basically has a denominator which is based on 2s, not 10s.
>

The proposal is more-or-less expressible as having epsilon = 2/:numbits -
presuming that the numerator and denominator are about the same size.

>From my POV the default epsilon is fine for practical use, but imprecise
enough to have this conversation come up repeatedly. Search this list for
"$epsilon = 1.0e-6 feels too big for Rat()"

How about setting the default epsilon to 1/2**32 or 1/2**64 and closing
that 2015 New Year's Eve post & this one too?

-y


Re: (default) Real->Rat precision should match what compiler uses for literals

2018-03-03 Thread Brad Gilbert
On Fri, Mar 2, 2018 at 4:33 PM, Jim Avera  wrote:
> Hello,
>
> Using Rakudo 2018.01:
>
> my Rat  $rat-from-literal = 1.23456789;
> my Rat  $rat-from-str = "1.23456789".Rat;
> my Real $real = 1.23456789e0;
> my Rat  $rat-from-real= $real.Rat;
>
> say $rat-from-literal.nude; # (123456789 1)
> say $rat-from-literal.Str;  # 1.23456789
> say $real.Str;  # 1.23456789
> say $rat-from-str.Str;  # 1.23456789
> say $rat-from-real.Str; # 1.234568   !?!
> say $rat-from-real.nude;# (100 81)
>
> From a user perspective, it's surprising that converting a Real to a Rat is
> by default not as precise as the compiler itself when it converts a literal
> to a Rat.

A Rat is a Real. The Real role only exists so that you can talk about
Numerics while excluding Complex numbers.
You are talking about floating point numbers which are of type Num.

If you change the epsilon to 1/1 they start to return what you expect

> (1.23456789e0,1.2345678e0)».Rat(1/1)
(1.23456789 1.2345678)

> (1.23456789e0,1.2345678e0)».Rat(1/1)».nude».join: '/'
(1356579/1098829 150479/121888)

> In particular, if the exact result can be represented in 64 bits (32-bit
> numerator & denom), throwing  away precision when converting from a 64-bit
> Real has no obvious practical benefit.  That is, throwing away precision
> does not save any memory (assuming Rat uses at least 32+32 -- which is just
> my assumption and might be wrong).

The Rat type uses up to a 64 bit unsigned integer as it's denominator,
the numerator is of arbitrary precision.

> As a programmer, I do not want Perl to throw away information without
> express permission, unless there is a practical necessity to do so, such as
> avoiding exploding memory or computation.

You are asking it to throw out the knowledge that it comes from a Num.

>
> ---
>
> I think the underlying problem is that Real to Rat conversion precision is
> controlled by an "epsilon" value which defaults to 1.0e-6 (see
> https://docs.perl6.org/routine/Rat).
>
> One could argue with the choice of default, but there may not exist an
> appropriate default which always DWIM!
>
> The reason is that I as a programmer don't actually want to limit precision
> per se; I only want to limit memory consumed by the result, and perhaps the
> cpu time needed to operate on that result.
>
> ---
>
> A solution might be to instead provide a pragmatic, rather than mathematical
> parameter:
>
> :$numbits = 64
>
> This would say to keep as much precision as possible while making the result
> fit in 64 bits.   For example 2.147483647e0.Rat would result in
> 2147483647/10 instead of 4310/2007.

The Num type basically has a denominator which is based on 2s, not 10s.
So the runtime has no idea that you expected it to have a denominator of
10 vs 1052513.

This number doesn't start stringifying to what you expect until it gets
an epsilon of 1/100

> $_ = 2.147483647e0.Rat(1/100)
2.147483647
> .nude.join: '/'
22602551/1052513

> If a mathematical epsilon is really what some programmers want (I'm
> doubtful), then both options could be provided:
>
> multi method Rat(Real:D: Real $epsilon)  # no default, used only if
> user really wants it
> multi method Rat(Real:D: Int $maxbits = 64)  # provides the default
> behavior
>
> I would appreciate any comments/explanations/insight on this topic!

Let's say that .Rat converts a Num to every last bit of precision it can.
The result could be so accurate that as soon as you do just about any
operation to it, it goes beyond what can be held in a Rat and becomes a Num.
(depending on the value)

For every one of the examples you have, it would do what you expect
if you converted to a Str before converting to a Rat.

> 1.23456789e0.Str.Rat
1.23456789
> 2.147483647e0.Str.Rat
2.147483647

At any rate the reason Real exists is so that you can accept any of
Rat / Num / Int

There could be a better default behaviour, but you haven't detailed
an algorithm to do it.