1 4 package gnu.math; 5 6 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 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 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 57 public boolean equals (Object 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 129 public static RealNum rationalize (RealNum x, RealNum y) 130 { 131 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 |