KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > math > RatNum


1 // Copyright (c) 1997 Per M.A. Bothner.
2
// This is free software; for terms and warranty disclaimer see ./COPYING.
3

4 package gnu.math;
5
6 /** The abstract class of rational numbers. */
7
8 public abstract class RatNum extends RealNum
9 {
10   public abstract IntNum numerator ();
11   public abstract IntNum denominator ();
12
13   public static RatNum make(IntNum num, IntNum den)
14   {
15     IntNum g = IntNum.gcd (num, den);
16     if (den.isNegative ())
17       g = IntNum.neg (g);
18     if (! g.isOne ())
19       {
20     num = IntNum.quotient (num, g);
21     den = IntNum.quotient (den, g);
22       }
23     return den.isOne () ? (RatNum)num : (RatNum)(new IntFraction (num, den));
24   }
25
26   public boolean isExact ()
27   {
28     return true;
29   }
30
31   public boolean isZero ()
32   {
33     return numerator().isZero();
34   }
35
36   /** Return exact "rational" infinity.
37   * @param sign either 1 or -1 for positive or negative infinity */

38   public static RatNum infinity(int sign)
39   {
40     return new IntFraction (IntNum.make(sign), IntNum.zero());
41   }
42
43   public static int compare (RatNum x, RatNum y)
44   {
45     return IntNum.compare (IntNum.times (x.numerator (), y.denominator ()),
46                IntNum.times (y.numerator (), x.denominator ()));
47   }
48
49   /* Assumes x and y are both canonicalized. */
50   public static boolean equals (RatNum x, RatNum y)
51   {
52     return IntNum.equals (x.numerator(), y.numerator())
53       && IntNum.equals (x.denominator(), y.denominator());
54   }
55
56   /* Assumes this and obj are both canonicalized. */
57   public boolean equals (Object JavaDoc obj)
58   {
59     if (obj == null || ! (obj instanceof RatNum))
60       return false;
61     return RatNum.equals (this, (RatNum) obj);
62   }
63
64   public static RatNum add (RatNum x, RatNum y, int k)
65   {
66     IntNum x_num = x.numerator();
67     IntNum x_den = x.denominator();
68     IntNum y_num = y.numerator();
69     IntNum y_den = y.denominator();
70     if (IntNum.equals (x_den, y_den))
71       return RatNum.make (IntNum.add (x_num, y_num, k), x_den);
72     return RatNum.make (IntNum.add (IntNum.times (y_den, x_num),
73                     IntNum.times (y_num, x_den), k),
74             IntNum.times (x_den, y_den));
75   }
76
77   public static RatNum times (RatNum x, RatNum y)
78   {
79     return RatNum.make (IntNum.times (x.numerator(), y.numerator()),
80             IntNum.times (x.denominator(), y.denominator()));
81   }
82
83   public static RatNum divide (RatNum x, RatNum y)
84   {
85     return RatNum.make (IntNum.times (x.numerator(), y.denominator()),
86             IntNum.times (x.denominator(), y.numerator()));
87   }
88
89   public Numeric power (IntNum y)
90   {
91     boolean inv;
92     if (y.isNegative())
93       {
94     inv = true;
95     y = IntNum.neg(y);
96       }
97     else
98       inv = false;
99     if (y.words == null)
100       {
101     IntNum num = IntNum.power (numerator(), y.ival);
102     IntNum den = IntNum.power (denominator(), y.ival);
103     return inv ? RatNum.make (den, num) : RatNum.make (num, den);
104       }
105     double d = doubleValue();
106     boolean neg = d < 0.0 && y.isOdd();
107     d = Math.pow (d, y.doubleValue());
108     if (inv)
109       d = 1.0/d;
110     return new DFloNum (neg ? -d : d);
111   }
112
113   public final RatNum toExact ()
114   {
115     return this;
116   }
117
118   public RealNum toInt (int rounding_mode)
119   {
120     return IntNum.quotient (numerator(), denominator(), rounding_mode);
121   }
122
123   public IntNum toExactInt (int rounding_mode)
124   {
125     return IntNum.quotient (numerator(), denominator(), rounding_mode);
126   }
127
128   /** Calcaulte the simplest rational between two reals. */
129   public static RealNum rationalize (RealNum x, RealNum y)
130   {
131     // This algorithm is by Alan Bawden. It has been transcribed
132
// with permission from C-Gambit, copyright Marc Feeley.
133
if (x.grt (y))
134       return simplest_rational2 (y, x);
135     else if (! (y.grt(x)))
136       return x;
137     else if (x.sign() > 0)
138       return simplest_rational2 (x, y);
139     else if (y.isNegative ())
140       return (RealNum) (simplest_rational2 ((RealNum)y.neg(),
141                         (RealNum)x.neg())).neg();
142     else
143       return IntNum.zero ();
144   }
145   private static RealNum simplest_rational2 (RealNum x, RealNum y)
146   {
147     RealNum fx = x.toInt (FLOOR);
148     RealNum fy = y.toInt (FLOOR);
149     if (! x.grt(fx))
150       return fx;
151     else if (fx.equals(fy))
152       {
153     RealNum n = (RealNum) IntNum.one().div(y.sub(fy));
154     RealNum d = (RealNum) IntNum.one().div(x.sub(fx));
155     return (RealNum) fx.add(IntNum.one().div(simplest_rational2 (n, d)),
156                 1);
157       }
158     else
159       return (RealNum) fx.add(IntNum.one(), 1);
160   }
161 }
162
Popular Tags