(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 & 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--