# New Ticket Created by Lanny Ripple # Please include the string: [perl #69550] # in the subject line of all future correspondence about this issue. # <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=69550 >
>From 8a240dd7b58e36d2b563a87c63eb89336662ddb9 Mon Sep 17 00:00:00 2001 From: Lanny Ripple <[email protected]> Date: Fri, 2 Oct 2009 15:00:18 -0500 Subject: [PATCH] add a cast for Num to Rat with optional error --- src/setting/Num.pm | 28 ++++++++++++++++++++++++++++ 1 files changed, 28 insertions(+), 0 deletions(-) diff --git a/src/setting/Num.pm b/src/setting/Num.pm index 27fa8e6..9f69133 100644 --- a/src/setting/Num.pm +++ b/src/setting/Num.pm @@ -250,6 +250,34 @@ class Num is also { ~self } + sub _modf($num) { my $q = $num.Int; $num - $q, $q; } + + multi method Rat($epsilon = 1.0e-6) { + my $num = +self; + my $signum = $num < 0 ?? -1 !! 1; + $num = -$num if $signum == -1; + + # Find convergents of the continued fraction. + + my ($r, $q) = _modf($num); + my ($a, $b) = 1, $q; + my ($c, $d) = 0, 1; + + while $r != 0 && abs($num - ($b/$d)) > $epsilon { + ($r, $q) = _modf(1/$r); + + ($a, $b) = ($b, $q*$b + $a); + ($c, $d) = ($d, $q*$d + $c); + } + + # Note that this result has less error than any Rational with a + # smaller denominator but it is not (necessarily) the Rational + # with the smallest denominator that has less than $epsilon error. + # However, to find that Rational would take more processing. + + Rat.new($signum * $b, $d); + } + our Num multi method sec($base = 'radians') { my $x = self!to-radians($base); Q:PIR { -- 1.6.0.4
