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
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
:$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!