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

[email protected] (Jim Avera) Fri, 2 Mar 2018 14:33:49 -0800
Newsgroups perl.perl6.language
Message-ID <[email protected]>
--------------F366021291E44648076976D3
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 8bit

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

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

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.

---

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/1000000000 instead of 4310/2007.

If a mathematical /epsilon/ is really what some programmers want (I'm 
doubtful), then both options could be provided:

multi methodRat(Real:D:Real$epsilon) # no default, used only if user 
really wants it
multi methodRat(Real:D:Int $maxbits = 64)  # provides the default behavior

I would appreciate any comments/explanations/insight on this topic!

-Jim


--------------F366021291E44648076976D3
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: 8bit

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <p>Hello,</p>
    <p>Using Rakudo 2018.01:<br>
    </p>
    <p><tt>    my Rat  $rat-from-literal = 1.23456789;<br>
            my Rat  $rat-from-str     = "1.23456789".Rat;<br>
            my Real $real             = 1.23456789e0;<br>
            my Rat  $rat-from-real    = $real.Rat;<br>
        <br>
            say $rat-from-literal.nude; # (123456789 100000000)<br>
            say $rat-from-literal.Str;  # 1.23456789<br>
            say $real.Str;              # 1.23456789<br>
            say $rat-from-str.Str;      # 1.23456789<br>
            say $rat-from-real.Str;     # 1.234568   !?!<br>
            say $rat-from-real.nude;    # (100 81)<br>
        <br>
      </tt>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. <br>
    </p>
    <p>In particular, if the exact result can be represented in 64 bits
      (32-bit numerator &amp; 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).<br>
    </p>
    <p>As a programmer,<i> I</i><i> do not want Perl to throw away
        information without express permission</i>, unless there is a
      practical necessity to do so, such as avoiding exploding memory or
      computation.<br>
    </p>
    <p>---</p>
    <p>I think the underlying problem is that Real to Rat conversion
      precision is controlled by an "epsilon" value which defaults to <span
        class="source perl6fe"><span class="constant numeric perl6fe"><span>1.0e-6
            (see <a moz-do-not-send="true"
              href="https://docs.perl6.org/routine/Rat">https://docs.perl6.org/routine/Rat</a>).  </span></span></span></p>
    <p><span class="source perl6fe"><span class="constant numeric
          perl6fe"><span>One could argue with the choice of default, but
            <i>there </i><i>may not exist</i><i> an appropriate default</i>
            which always DWIM!<br>
          </span></span></span></p>
    <p><span class="source perl6fe"><span class="constant numeric
          perl6fe"><span>The reason is that I as a programmer don't
            actually want to limit precision <i>per se; </i>I only
            want to limit memory consumed by the result, and perhaps the
            cpu time needed to operate on that result.  <br>
          </span></span></span></p>
    ---<br>
    <p>A solution might be to instead provide a pragmatic, rather than
      mathematical parameter:</p>
    <p>    :$numbits = 64</p>
    <p>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/1000000000 instead of 4310/2007.<br>
    </p>
    <p>If a mathematical <i>epsilon</i> is really what some programmers
      want (I'm doubtful), then both options could be provided:<tt><br>
        <br>
      </tt><tt>    </tt><tt><span class="source perl6fe"><span
            class="storage type declarator type perl6fe"><span>multi
              method</span></span><span> </span><span class="entity name
            function perl6fe"><span>Rat</span></span><span>(</span><span
            class="support type perl6fe"><span>Real</span></span><span
            class="meta adverb definedness perl6fe"><span class="keyword
              operator adverb perl6fe"><span>:</span></span><span
              class="keyword other special-method definedness perl6fe"><span>D</span></span></span><span
            class="keyword operator generic perl6fe"><span>:</span></span><span> </span><span
            class="support type perl6fe"><span>Real</span></span><span> </span><span
            class="meta variable container perl6fe"><span
              class="variable other identifier sigil perl6fe"><span>$</span></span><span
              class="variable other identifier perl6fe"><span>epsilon</span></span></span><span>)     
            # no default, used only if user really wants it<br>
                </span></span></tt><tt><span class="source perl6fe"><span
            class="storage type declarator type perl6fe"><span>multi
              method</span></span><span> </span><span class="entity name
            function perl6fe"><span>Rat</span></span><span>(</span><span
            class="support type perl6fe"><span>Real</span></span><span
            class="meta adverb definedness perl6fe"><span class="keyword
              operator adverb perl6fe"><span>:</span></span><span
              class="keyword other special-method definedness perl6fe"><span>D</span></span></span><span
            class="keyword operator generic perl6fe"><span>:</span></span><span>
          </span><span>Int $maxbits = 64)  # provides the default
            behavior</span></span></tt></p>
    <p>I would appreciate any comments/explanations/insight on this
      topic!</p>
    <p>-Jim<br>
    </p>
    <span class="source perl6fe"><span></span></span>
    <p><span class="source perl6fe"><span class="constant numeric
          perl6fe"><span></span></span><span></span></span></p>
  </body>
</html>

--------------F366021291E44648076976D3--