1 9 package org.jscience.mathematics.numbers; 10 11 import org.jscience.mathematics.structures.Field; 12 13 import javolution.text.Text; 14 import javolution.xml.XMLFormat; 15 import javolution.xml.stream.XMLStreamException; 16 17 29 public final class Rational extends Number <Rational> implements Field<Rational>{ 30 31 36 protected static final XMLFormat<Rational> XML = new XMLFormat<Rational>(Rational.class) { 37 38 @Override 39 public Rational newInstance(Class <Rational> cls, InputElement xml) throws XMLStreamException { 40 return Rational.valueOf(xml.getAttribute("value")); 41 } 42 43 public void write(Rational rational, OutputElement xml) throws XMLStreamException { 44 xml.setAttribute("value", rational.toText()); 45 } 46 47 public void read(InputElement xml, Rational rational) { 48 } 50 }; 51 52 55 private static final Factory<Rational> FACTORY = new Factory<Rational>() { 56 57 protected Rational create() { 58 return new Rational(); 59 } 60 }; 61 62 65 public static final Rational ZERO = new Rational(LargeInteger.ZERO, 66 LargeInteger.ONE); 67 68 71 public static final Rational ONE = new Rational(LargeInteger.ONE, 72 LargeInteger.ONE); 73 74 77 private LargeInteger _dividend; 78 79 82 private LargeInteger _divisor; 83 84 87 private Rational() { 88 } 89 90 98 private Rational(LargeInteger dividend, LargeInteger divisor) { 99 _dividend = dividend; 100 _divisor = divisor; 101 } 102 103 112 public static Rational valueOf(long dividend, long divisor) { 113 Rational r = FACTORY.object(); 114 r._dividend = LargeInteger.valueOf(dividend); 115 r._divisor = LargeInteger.valueOf(divisor); 116 return r.normalize(); 117 } 118 119 128 public static Rational valueOf(LargeInteger dividend, LargeInteger divisor) { 129 Rational r = FACTORY.object(); 130 r._dividend = dividend; 131 r._divisor = divisor; 132 return r.normalize(); 133 } 134 135 141 public static Rational valueOf(CharSequence chars) { 142 Text txt = Text.valueOf(chars); int sep = txt.indexOf("/"); 144 if (sep >= 0) { 145 LargeInteger dividend = LargeInteger.valueOf(txt.subtext(0, sep)); 146 LargeInteger divisor = LargeInteger.valueOf(txt.subtext( 147 sep + 1, chars.length())); 148 return valueOf(dividend, divisor); 149 } else { return valueOf(LargeInteger.valueOf(txt.subtext(0, sep)), 151 LargeInteger.ONE); 152 } 153 } 154 155 161 public LargeInteger getDividend() { 162 return _dividend; 163 } 164 165 171 public LargeInteger getDivisor() { 172 return _divisor; 173 } 174 175 180 public LargeInteger round() { 181 return _dividend.divide(_divisor); 182 } 183 184 189 public Rational opposite() { 190 return Rational.valueOf(_dividend.opposite(), _divisor); 191 } 192 193 199 public Rational plus(Rational that) { 200 return Rational.valueOf( 201 this._dividend.times(that._divisor).plus( 202 this._divisor.times(that._dividend)), 203 this._divisor.times(that._divisor)).normalize(); 204 } 205 206 213 public Rational minus(Rational that) { 214 return Rational.valueOf( 215 this._dividend.times(that._divisor).minus( 216 this._divisor.times(that._dividend)), 217 this._divisor.times(that._divisor)).normalize(); 218 } 219 220 226 public Rational times(Rational that) { 227 Rational r = Rational.valueOf(this._dividend.times(that._dividend), 228 this._divisor.times(that._divisor)).normalize(); 229 return r; 230 } 231 232 238 public Rational inverse() { 239 if (_dividend.isZero()) 240 throw new ArithmeticException ("Dividend is zero"); 241 return _dividend.isNegative() ? Rational.valueOf(_divisor.opposite(), 242 _dividend.opposite()) : Rational.valueOf(_divisor, _dividend); 243 } 244 245 252 public Rational divide(Rational that) { 253 return Rational.valueOf(this._dividend.times(that._divisor), 254 this._divisor.times(that._dividend)).normalize(); 255 } 256 257 262 public Rational abs() { 263 return Rational.valueOf(_dividend.abs(), _divisor); 264 } 265 266 272 public boolean isLargerThan(Rational that) { 273 return this._dividend.times(that._divisor).isLargerThan( 274 that._dividend.times(this._divisor)); 275 } 276 277 282 public Text toText() { 283 return _dividend.toText().concat(Text.valueOf('/')).concat( 284 _divisor.toText()); 285 } 286 287 293 public Text toText(int radix) { 294 return _dividend.toText(radix).concat(Text.valueOf('/')).concat( 295 _divisor.toText(radix)); 296 } 297 298 305 public boolean equals(Object that) { 306 if (that instanceof Rational) { 307 return this._dividend.equals(((Rational) that)._dividend) 308 && this._divisor.equals(((Rational) that)._divisor); 309 } else { 310 return false; 311 } 312 } 313 314 319 public int hashCode() { 320 return _dividend.hashCode() - _divisor.hashCode(); 321 } 322 323 329 public long longValue() { 330 return (long) doubleValue(); 331 } 332 333 339 public double doubleValue() { 340 int dividendBitLength = _dividend.bitLength(); 342 int divisorBitLength = _divisor.bitLength(); 343 if (dividendBitLength > divisorBitLength) { 344 int shift = divisorBitLength - 63;; 346 long divisor = _divisor.shiftRight(shift).longValue(); 347 LargeInteger dividend = _dividend.shiftRight(shift); 348 return dividend.doubleValue() / divisor; 349 } else { 350 int shift = dividendBitLength - 63;; 352 long dividend = _dividend.shiftRight(shift).longValue(); 353 LargeInteger divisor = _divisor.shiftRight(shift); 354 return dividend / divisor.doubleValue(); 355 } 356 } 357 358 365 public int compareTo(Rational that) { 366 return this._dividend.times(that._divisor).compareTo( 367 that._dividend.times(this._divisor)); 368 } 369 370 376 private Rational normalize() { 377 if (!_divisor.isZero()) { 378 if (_divisor.isPositive()) { 379 LargeInteger gcd = _dividend.gcd(_divisor); 380 if (!gcd.equals(LargeInteger.ONE)) { 381 _dividend = _dividend.divide(gcd); 382 _divisor = _divisor.divide(gcd); 383 } 384 return this; 385 } else { 386 _dividend = _dividend.opposite(); 387 _divisor = _divisor.opposite(); 388 return normalize(); 389 } 390 } else { 391 throw new ArithmeticException ("Zero divisor"); 392 } 393 } 394 395 public boolean move(ObjectSpace os) { 397 if (super.move(os)) { 398 _dividend.move(os); 399 _divisor.move(os); 400 return true; 401 } 402 return false; 403 } 404 405 private static final long serialVersionUID = 1L; 406 407 } | Popular Tags |