# New Ticket Created by Sol Foster
# Please include the string: [perl #68926]
# in the subject line of all future correspondence about this issue.
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=68926 >
More-or-less complete rewrite of the rat.t tests for Rat, making them more
thorough, more robust, and comforming to the new specs for them discussed
today on #perl6. Minor corresponding changes to Rat.pm as well.
--
Sol Foster: [email protected]
>From d98b41530782404c257e72a9c04bc63f86ead550 Mon Sep 17 00:00:00 2001
From: [email protected] <[email protected]>
Date: Tue, 1 Sep 2009 16:26:45 -0400
Subject: [PATCH] Move Rat.Str to new standard, add Rat.nude.
---
src/setting/Rat.pm | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/setting/Rat.pm b/src/setting/Rat.pm
index c9dcdf0..7fc8329 100644
--- a/src/setting/Rat.pm
+++ b/src/setting/Rat.pm
@@ -2,12 +2,10 @@ class Rat {
has $.numerator;
has $.denominator;
- my sub gcd(Int $a is copy, Int $b is copy)
- {
+ my sub gcd(Int $a is copy, Int $b is copy) {
$a = -$a if ($a < 0);
$b = -$b if ($b < 0);
- while $a > 0 && $b > 0
- {
+ while $a > 0 && $b > 0 {
($a, $b) = ($b, $a) if ($b > $a);
$a %= $b;
}
@@ -27,9 +25,11 @@ class Rat {
multi method perl() { "$!numerator/$!denominator"; }
- multi method Str() { $.Num.Str }
-
multi method Num() { $!numerator.Num / $!denominator.Num }
+
+ multi method Str() { $.Num.Str; }
+
+ multi method nude() { $.numerator, $.denominator; }
}
multi sub infix:<+>(Rat $a, Rat $b) {
--
1.6.0.5
Index: t/spec/S32-num/rat.t
===================================================================
--- t/spec/S32-num/rat.t (revision 28161)
+++ t/spec/S32-num/rat.t (working copy)
@@ -7,39 +7,84 @@
# Basic test functions specific to rational numbers.
# Test ~
-is(~(Rat.new(2,3)), "2/3", "Rats stringify properly");
-is(~(Rat.new(-1,7)), "-1/7", "Rats stringify properly");
+is(~(Rat.new(1,4)), ~(0.25), "Rats stringify properly");
+is(~(Rat.new(-1,2)), ~(-0.5), "Rats stringify properly");
+is(~(Rat.new(7,4)), ~(1.75), "Rats stringify properly");
+is(~(Rat.new(7,-1)), ~(-7), "Rats stringify properly");
# Test new
-is(~(Rat.new(1,-7)), "-1/7", "Negative signs move to numerator");
-is(~(Rat.new(-32,-33)), "32/33", "Double negatives cancel out");
-is(~(Rat.new(2,4)), "1/2", "Reduce to simplest form in constructor");
-is(~(Rat.new(39,33)), "13/11", "Reduce to simplest form in constructor");
-is(~(Rat.new(0,33)), "0/1", "Reduce to simplest form in constructor");
-is(~(Rat.new(1451234131,60)), "1451234131/60", "Reduce huge number to simplest
form in constructor");
+is(Rat.new(1, -7).nude, (-1, 7), "Negative signs move to numerator");
+is(Rat.new(-32, -33).nude, (32, 33), "Double negatives cancel out");
+is(Rat.new(2, 4).nude, (1, 2), "Reduce to simplest form in constructor");
+is(Rat.new(39, 33).nude, (13, 11), "Reduce to simplest form in constructor");
+is(Rat.new(0, 33).nude, (0, 1), "Reduce to simplest form in constructor");
+is(Rat.new(1451234131, 60).nude, (1451234131, 60), "Reduce huge number to
simplest form in constructor");
# Test basic math
-is(~(1 / 4 + 1 / 4), "1/2", "1/4 + 1/4 = 1/2");
-is(~(1 / 4 + 2 / 7), "15/28", "1/4 + 2/7 = 15/28");
-is(~(1 / 4 + 1), "5/4", "1/4 + 1 = 5/4");
-is(~(1 + 1 / 4), "5/4", "1 + 1/4 = 5/4");
+is(1 / 4 + 1 / 4, 1/2, "1/4 + 1/4 = 1/2");
+isa_ok(1 / 4 + 1 / 4, Rat, "1/4 + 1/4 is a Rat");
+is(1 / 4 + 2 / 7, 15/28, "1/4 + 2/7 = 15/28");
+is(1 / 4 + 1, 5/4, "1/4 + 1 = 5/4");
+isa_ok(1 / 4 + 1, Rat, "1/4 + 1 is a Rat");
+is(1 + 1 / 4, 5/4, "1 + 1/4 = 5/4");
+isa_ok(1 + 1 / 4, Rat, "1 + 1/4 is a Rat");
+
+is(1 / 4 - 1 / 4, 0/1, "1/4 - 1/4 = 0/1");
+is(1 / 4 - 3 / 4, -1/2, "1/4 - 3/4 = -1/2");
+is((1 / 4 - 3 / 4).nude, (-1, 2), "1/4 - 3/4 = -1/2 is simplified internally");
+isa_ok((1 / 4 - 3 / 4), Rat, "1/4 - 3/4 is a Rat");
+is(1 / 4 - 1, -3/4, "1/4 - 1 = -3/4");
+isa_ok(1 / 4 - 1, Rat, "1/4 - 1 is a Rat");
+is(1 - 1 / 4, 3/4, "1 - 1/4 = 3/4");
+isa_ok(1 - 1 / 4, Rat, "1 - 1/4 is a Rat");
+
+is((2 / 3) * (5 / 4), 5/6, "2/3 * 5/4 = 5/6");
+is(((2 / 3) * (5 / 4)).nude, (5, 6), "2/3 * 5/4 = 5/6 is simplified
internally");
+isa_ok((2 / 3) * (5 / 4), Rat, "2/3 * 5/4 is a Rat");
+is((2 / 3) * 2, 4/3, "2/3 * 2 = 4/3");
+isa_ok((2 / 3) * 2, Rat, "2/3 * 2 is a Rat");
+is(((2 / 3) * 3).nude, (2, 1), "2/3 * 3 = 2 is simplified internally");
+is(2 * (2 / 3), 4/3, "2 * 2/3 = 4/3");
+isa_ok(2 * (2 / 3), Rat, "2 * 2/3 is a Rat");
+is((3 * (2 / 3)).nude, (2, 1), "3 * 2/3 = 2 is simplified internally");
+
+is((2 / 3) / (5 / 4), 8/15, "2/3 / 5/4 = 8/15");
+isa_ok((2 / 3) / (5 / 4), Rat, "2/3 / 5/4 is a Rat");
+is((2 / 3) / 2, 1/3, "2/3 / 2 = 1/3");
+is(((2 / 3) / 2).nude, (1, 3), "2/3 / 2 = 1/3 is simplified internally");
+isa_ok((2 / 3) / 2, Rat, "2/3 / 2 is a Rat");
+is(2 / (1 / 3), 6, "2 / 1/3 = 6");
+isa_ok(2 / (1 / 3), Rat, "2 / 1/3 is a Rat");
+is((2 / (2 / 3)).nude, (3, 1), "2 / 2/3 = 3 is simplified internally");
-is(~(1 / 4 - 1 / 4), "0/1", "1/4 - 1/4 = 0/1");
-is(~(1 / 4 - 3 / 4), "-1/2", "1/4 - 3/4 = -1/2");
-is(~(1 / 4 - 1), "-3/4", "1/4 - 1 = -3/4");
-is(~(1 - 1 / 4), "3/4", "1 - 1/4 = 3/4");
+# Give the arithmetical operators a workout
-is(~((2 / 3) * (5 / 4)), "5/6", "2/3 * 5/4 = 5/6");
-is(~((2 / 3) * 2), "4/3", "2/3 * 2 = 4/3");
-is(~(2 * (2 / 3)), "4/3", "2 * 2/3 = 4/3");
+for (1/2, 2/3, -1/4, 4/5, 2/7, 65/8) -> $a {
+ for (-7, -1, 0, 1, 2, 5, 7, 42) -> $b {
+ is_approx($a + $b, $a.Num + $b.Num, "Rat + Int works");
+ is_approx($b + $a, $b.Num + $a.Num, "Int + Rat works");
+ is_approx($a - $b, $a.Num - $b.Num, "Rat - Int works");
+ is_approx($b - $a, $b.Num - $a.Num, "Int - Rat works");
+ is_approx($a * $b, $a.Num * $b.Num, "Rat * Int works");
+ is_approx($b * $a, $b.Num * $a.Num, "Int * Rat works");
+ is_approx($a / $b, $a.Num / $b.Num, "Rat / Int works") if $b != 0;
+ is_approx($b / $a, $b.Num / $a.Num, "Int / Rat works");
+ }
+
+ for (1/2, 2/3, -1/4, 4/5, 2/7, 65/8) -> $b {
+ is_approx($a + $b, $a.Num + $b.Num, "Rat + Rat works");
+ is_approx($b + $a, $b.Num + $a.Num, "Rat + Rat works");
+ is_approx($a - $b, $a.Num - $b.Num, "Rat - Rat works");
+ is_approx($b - $a, $b.Num - $a.Num, "Rat - Rat works");
+ is_approx($a * $b, $a.Num * $b.Num, "Rat * Rat works");
+ is_approx($b * $a, $b.Num * $a.Num, "Rat * Rat works");
+ is_approx($a / $b, $a.Num / $b.Num, "Rat / Rat works");
+ is_approx($b / $a, $b.Num / $a.Num, "Rat / Rat works");
+ }
+}
-is(~((2 / 3) / (5 / 4)), "8/15", "2/3 / 5/4 = 8/15");
-is(~((2 / 3) / 2), "1/3", "2/3 / 2 = 1/3");
-is(~(2 / (1 / 3)), "3/2", "2 / 1/3 = 3/2");
+# SHOULD: Add divide by zero / zero denominator tests
-
-
-
done_testing;
# vim: ft=perl6