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!


Reply via email to