001/* 002 * $Id: BigDecimal.java 4125 2012-08-19 19:05:22Z kredel $ 003 */ 004 005package edu.jas.arith; 006 007 008import java.io.Reader; 009import java.math.MathContext; 010import java.util.ArrayList; 011import java.util.List; 012import java.util.Random; 013 014import edu.jas.kern.StringUtil; 015import edu.jas.structure.GcdRingElem; 016import edu.jas.structure.RingFactory; 017 018 019/** 020 * BigDecimal class to make java.math.BigDecimal available with RingElem 021 * interface. Objects of this class are immutable. Experimental, use with care, 022 * compareTo is hacked. 023 * @author Heinz Kredel 024 * @see java.math.BigDecimal 025 */ 026 027public final class BigDecimal implements GcdRingElem<BigDecimal>, RingFactory<BigDecimal> { 028 029 030 /** 031 * The data structure. 032 */ 033 public final java.math.BigDecimal val; 034 035 036 private final static Random random = new Random(); 037 038 039 // should go to factory: 040 public static final int DEFAULT_PRECISION = 50; 041 042 043 public static final MathContext DEFAULT_CONTEXT = new MathContext(DEFAULT_PRECISION); 044 045 046 public final MathContext context; 047 048 049 /** 050 * The constant 0. 051 */ 052 public final static BigDecimal ZERO = new BigDecimal(java.math.BigDecimal.ZERO); 053 054 055 /** 056 * The constant 1. 057 */ 058 public final static BigDecimal ONE = new BigDecimal(java.math.BigDecimal.ONE); 059 060 061 /** 062 * Constructor for BigDecimal from math.BigDecimal. 063 * @param a java.math.BigDecimal. 064 */ 065 public BigDecimal(java.math.BigDecimal a) { 066 this(a, DEFAULT_CONTEXT); 067 } 068 069 070 /** 071 * Constructor for BigDecimal from math.BigDecimal. 072 * @param a java.math.BigDecimal. 073 * @param mc MathContext. 074 */ 075 public BigDecimal(java.math.BigDecimal a, MathContext mc) { 076 val = a; 077 context = mc; 078 } 079 080 081 /** 082 * Constructor for BigDecimal from long. 083 * @param a long. 084 */ 085 public BigDecimal(long a) { 086 this(a, DEFAULT_CONTEXT); 087 } 088 089 090 /** 091 * Constructor for BigDecimal from long and a context. 092 * @param a long. 093 * @param mc MathContext. 094 */ 095 public BigDecimal(long a, MathContext mc) { 096 this(new java.math.BigDecimal(String.valueOf(a)), mc); 097 } 098 099 100 /** 101 * Constructor for BigDecimal from double. 102 * @param a double. 103 */ 104 public BigDecimal(double a) { 105 this(a, DEFAULT_CONTEXT); 106 } 107 108 109 /** 110 * Constructor for BigDecimal from double and a context. 111 * @param a double. 112 * @param mc MathContext. 113 */ 114 public BigDecimal(double a, MathContext mc) { 115 this(new java.math.BigDecimal(a), mc); 116 } 117 118 119 /** 120 * Constructor for BigDecimal from java.math.BigInteger. 121 * @param a java.math.BigInteger. 122 */ 123 public BigDecimal(java.math.BigInteger a) { 124 this(a, DEFAULT_CONTEXT); 125 } 126 127 128 /** 129 * Constructor for BigDecimal from java.math.BigInteger. 130 * @param a java.math.BigInteger. 131 * @param mc MathContext. 132 */ 133 public BigDecimal(java.math.BigInteger a, MathContext mc) { 134 this(new java.math.BigDecimal(a), mc); 135 } 136 137 138 /** 139 * Constructor for BigDecimal from BigRational. 140 * @param a edu.jas.arith.BigRational. 141 */ 142 public BigDecimal(BigRational a) { 143 this(a, DEFAULT_CONTEXT); 144 } 145 146 147 /** 148 * Constructor for BigDecimal from BigRational. 149 * @param a edu.jas.arith.BigRational. 150 * @param mc MathContext. 151 */ 152 public BigDecimal(BigRational a, MathContext mc) { 153 this((new java.math.BigDecimal(a.num)).divide(new java.math.BigDecimal(a.den), mc), mc); 154 } 155 156 157 /** 158 * Constructor for BigDecimal from String. 159 * @param s String. 160 */ 161 public BigDecimal(String s) { 162 this(s, DEFAULT_CONTEXT); 163 } 164 165 166 /** 167 * Constructor for BigDecimal from String. 168 * @param s String. 169 * @param mc MathContext. 170 */ 171 public BigDecimal(String s, MathContext mc) { 172 this(new java.math.BigDecimal(s.trim()), mc); 173 } 174 175 176 /** 177 * Constructor for BigDecimal without parameters. 178 */ 179 public BigDecimal() { 180 this(java.math.BigDecimal.ZERO, DEFAULT_CONTEXT); 181 } 182 183 184 /** 185 * Get the value. 186 * @return val java.math.BigDecimal. public java.math.BigDecimal getVal() { 187 * return val; } 188 */ 189 190 191 /** 192 * Get the corresponding element factory. 193 * @return factory for this Element. 194 * @see edu.jas.structure.Element#factory() 195 */ 196 public BigDecimal factory() { 197 return this; 198 } 199 200 201 /** 202 * Get a list of the generating elements. 203 * @return list of generators for the algebraic structure. 204 * @see edu.jas.structure.ElemFactory#generators() 205 */ 206 public List<BigDecimal> generators() { 207 List<BigDecimal> g = new ArrayList<BigDecimal>(1); 208 g.add(getONE()); 209 return g; 210 } 211 212 213 /** 214 * Is this structure finite or infinite. 215 * @return true if this structure is finite, else false. 216 * @see edu.jas.structure.ElemFactory#isFinite() <b>Note: </b> is actually 217 * finite but returns false. 218 */ 219 public boolean isFinite() { 220 return false; 221 } 222 223 224 /** 225 * Clone this. 226 * @see java.lang.Object#clone() 227 */ 228 @Override 229 public BigDecimal copy() { 230 return new BigDecimal(val, context); 231 } 232 233 234 /** 235 * Copy BigDecimal element c. 236 * @param c BigDecimal. 237 * @return a copy of c. 238 */ 239 public BigDecimal copy(BigDecimal c) { 240 return new BigDecimal(c.val, c.context); 241 } 242 243 244 /** 245 * Get the zero element. 246 * @return 0. 247 */ 248 public BigDecimal getZERO() { 249 return ZERO; 250 } 251 252 253 /** 254 * Get the one element. 255 * @return 1. 256 */ 257 public BigDecimal getONE() { 258 return ONE; 259 } 260 261 262 /** 263 * Query if this ring is commutative. 264 * @return true. 265 */ 266 public boolean isCommutative() { 267 return true; 268 } 269 270 271 /** 272 * Query if this ring is associative. Floating point number addition is not 273 * associative, but multiplication is. 274 * @return true. 275 */ 276 public boolean isAssociative() { 277 return true; 278 } 279 280 281 /** 282 * Query if this ring is a field. 283 * @return true. 284 */ 285 public boolean isField() { 286 return true; 287 } 288 289 290 /** 291 * Characteristic of this ring. 292 * @return characteristic of this ring. 293 */ 294 public java.math.BigInteger characteristic() { 295 return java.math.BigInteger.ZERO; 296 } 297 298 299 /** 300 * Get a BigDecimal element from a math.BigDecimal. 301 * @param a math.BigDecimal. 302 * @return a as BigDecimal. 303 */ 304 public BigDecimal fromInteger(java.math.BigInteger a) { 305 return new BigDecimal(new java.math.BigDecimal(a), context); 306 } 307 308 309 /** 310 * Get a BigDecimal element from a math.BigDecimal. 311 * @param a math.BigDecimal. 312 * @return a as BigDecimal. 313 */ 314 public static BigDecimal valueOf(java.math.BigDecimal a) { 315 return new BigDecimal(a, DEFAULT_CONTEXT); 316 } 317 318 319 /** 320 * Get a BigDecimal element from long. 321 * @param a long. 322 * @return a as BigDecimal. 323 */ 324 public BigDecimal fromInteger(long a) { 325 return new BigDecimal(a, context); 326 } 327 328 329 /** 330 * Get a BigDecimal element from long. 331 * @param a long. 332 * @return a as BigDecimal. 333 */ 334 public static BigDecimal valueOf(long a) { 335 return new BigDecimal(a, DEFAULT_CONTEXT); 336 } 337 338 339 /** 340 * Is BigDecimal number zero. 341 * @return If this is 0 then true is returned, else false. 342 * @see edu.jas.structure.RingElem#isZERO() 343 */ 344 public boolean isZERO() { 345 return val.compareTo(java.math.BigDecimal.ZERO) == 0; 346 } 347 348 349 /** 350 * Is BigDecimal number one. 351 * @see edu.jas.structure.RingElem#isONE() 352 */ 353 public boolean isONE() { 354 return val.compareTo(java.math.BigDecimal.ONE) == 0; 355 } 356 357 358 /** 359 * Is BigDecimal number unit. 360 * @see edu.jas.structure.RingElem#isUnit() 361 */ 362 public boolean isUnit() { 363 return (!isZERO()); 364 } 365 366 367 /** 368 * Get the String representation. 369 * @see java.lang.Object#toString() 370 */ 371 @Override 372 public String toString() { 373 //return val.toString() + "(ulp=" + val.ulp() + ")"; 374 return val.toString(); 375 } 376 377 378 /** 379 * Get a scripting compatible string representation. 380 * @return script compatible representation for this Element. 381 * @see edu.jas.structure.Element#toScript() 382 */ 383 //JAVA6only: @Override 384 public String toScript() { 385 // Python case 386 return toString(); 387 } 388 389 390 /** 391 * Get a scripting compatible string representation of the factory. 392 * @return script compatible representation for this ElemFactory. 393 * @see edu.jas.structure.Element#toScriptFactory() 394 */ 395 //JAVA6only: @Override 396 public String toScriptFactory() { 397 // Python case 398 return "DD()"; 399 } 400 401 402 /** 403 * Compare to BigDecimal b. Experimental, is hacked. 404 * @param b BigDecimal. 405 * @return 0 if abs(this-b) < epsilon, 1 if this > b, -1 if this < b. 406 */ 407 //JAVA6only: @Override 408 public int compareTo(BigDecimal b) { 409 //if (false) { 410 // return val.compareTo(b.val); 411 //} 412 java.math.BigDecimal s = val.subtract(b.val, context); 413 java.math.BigDecimal u1 = val.ulp(); 414 java.math.BigDecimal u2 = b.val.ulp(); 415 int u = Math.min(u1.scale(), u2.scale()); 416 //System.out.println("u = " + u + ", s = " + s); 417 java.math.BigDecimal eps; 418 if (u <= 0) { 419 eps = u1.max(u2); 420 } else { 421 eps = u1.min(u2); 422 } 423 //eps = eps.movePointRight(1); 424 //System.out.println("ctx = " + context); 425 //System.out.println("eps = " + eps); 426 int t = s.abs().compareTo(eps); 427 if (t < 1) { 428 return 0; 429 } 430 return s.signum(); 431 } 432 433 434 /** 435 * Comparison with any other object. 436 * @see java.lang.Object#equals(java.lang.Object) 437 */ 438 @Override 439 public boolean equals(Object b) { 440 if (!(b instanceof BigDecimal)) { 441 return false; 442 } 443 BigDecimal bi = (BigDecimal) b; 444 return val.equals(bi.val); 445 } 446 447 448 /** 449 * Hash code for this BigDecimal. 450 * @see java.lang.Object#hashCode() 451 */ 452 @Override 453 public int hashCode() { 454 return val.hashCode(); 455 } 456 457 458 /** 459 * Absolute value of this. 460 * @see edu.jas.structure.RingElem#abs() 461 */ 462 public BigDecimal abs() { 463 return new BigDecimal(val.abs(), context); 464 } 465 466 467 /* Negative value of this. 468 * @see edu.jas.structure.RingElem#negate() 469 */ 470 public BigDecimal negate() { 471 return new BigDecimal(val.negate(), context); 472 } 473 474 475 /** 476 * signum. 477 * @see edu.jas.structure.RingElem#signum() 478 */ 479 public int signum() { 480 return val.signum(); 481 } 482 483 484 /** 485 * BigDecimal subtract. 486 * @param S BigDecimal. 487 * @return this-S. 488 */ 489 public BigDecimal subtract(BigDecimal S) { 490 return new BigDecimal(val.subtract(S.val, context)); 491 } 492 493 494 /** 495 * BigDecimal divide. 496 * @param S BigDecimal. 497 * @return this/S. 498 */ 499 public BigDecimal divide(BigDecimal S) { 500 return new BigDecimal(val.divide(S.val, context)); 501 } 502 503 504 /** 505 * Integer inverse. R is a non-zero integer. S=1/R if defined else 0. 506 * @see edu.jas.structure.RingElem#inverse() 507 */ 508 public BigDecimal inverse() { 509 return ONE.divide(this); 510 } 511 512 513 /** 514 * BigDecimal remainder. 515 * @param S BigDecimal. 516 * @return this - (this/S)*S. 517 */ 518 public BigDecimal remainder(BigDecimal S) { 519 return new BigDecimal(val.remainder(S.val, context)); 520 } 521 522 523 /** 524 * BigDecimal compute quotient and remainder. 525 * @param S BigDecimal. 526 * @return BigDecimal[] { q, r } with q = this/S and r = rem(this,S). 527 */ 528 public BigDecimal[] quotientRemainder(BigDecimal S) { 529 BigDecimal[] qr = new BigDecimal[2]; 530 java.math.BigDecimal[] C = val.divideAndRemainder(S.val, context); 531 qr[0] = new BigDecimal(C[0]); 532 qr[1] = new BigDecimal(C[1]); 533 return qr; 534 } 535 536 537 /** 538 * BigDecimal compute quotient and remainder. 539 * @param S BigDecimal. 540 * @return BigDecimal[] { q, r } with q = this/S and r = rem(this,S). 541 * @deprecated use quotientRemainder() 542 */ 543 @Deprecated 544 public BigDecimal[] divideAndRemainder(BigDecimal S) { 545 return quotientRemainder(S); 546 } 547 548 549 /** 550 * BigDecimal greatest common divisor. 551 * @param S BigDecimal. 552 * @return gcd(this,S). 553 */ 554 public BigDecimal gcd(BigDecimal S) { 555 throw new UnsupportedOperationException("BigDecimal.gcd() not implemented"); 556 //return new BigDecimal( val.gcd( S.val ) ); 557 } 558 559 560 /** 561 * BigDecimal extended greatest common divisor. 562 * @param S BigDecimal. 563 * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). 564 */ 565 public BigDecimal[] egcd(BigDecimal S) { 566 throw new UnsupportedOperationException("BigDecimal.egcd() not implemented"); 567 } 568 569 570 /** 571 * BigDecimal random. 572 * @param n such that 0 ≤ val(r) ≤ (2<sup>n</sup>-1). 0 ≤ exp(r) 573 * ≤ (100-1). 574 * @return r, a random BigDecimal. 575 */ 576 public BigDecimal random(int n) { 577 return random(n, random); 578 } 579 580 581 /** 582 * BigDecimal random. 583 * @param n such that 0 ≤ val(r) ≤ (2<sup>n</sup>-1). 0 ≤ exp(r) 584 * ≤ (100-1). 585 * @param rnd is a source for random bits. 586 * @return r, a random BigDecimal. 587 */ 588 public BigDecimal random(int n, Random rnd) { 589 return random(n, 100, rnd); 590 } 591 592 593 /** 594 * BigDecimal random. 595 * @param n such that 0 ≤ val(r) ≤ (2<sup>n</sup>-1). 596 * @param e such that 0 ≤ exp(r) ≤ (e-1). 597 * @return r, a random BigDecimal. 598 */ 599 public BigDecimal random(int n, int e) { 600 return random(n, e, random); 601 } 602 603 604 /** 605 * BigDecimal random. 606 * @param n such that 0 ≤ val(r) ≤ (2<sup>n</sup>-1). 607 * @param e such that 0 ≤ exp(r) ≤ (e-1). 608 * @param rnd is a source for random bits. 609 * @return r, a random BigDecimal. 610 */ 611 public BigDecimal random(int n, int e, Random rnd) { 612 java.math.BigInteger r = new java.math.BigInteger(n, rnd); 613 if (rnd.nextBoolean()) { 614 r = r.negate(); 615 } 616 int scale = rnd.nextInt(e); 617 if (rnd.nextBoolean()) { 618 scale = -scale; 619 } 620 java.math.BigDecimal d = new java.math.BigDecimal(r, scale, context); 621 return new BigDecimal(d, context); 622 } 623 624 625 /** 626 * BigDecimal multiply. 627 * @param S BigDecimal. 628 * @return this*S. 629 */ 630 public BigDecimal multiply(BigDecimal S) { 631 return new BigDecimal(val.multiply(S.val, context)); 632 } 633 634 635 /** 636 * BigDecimal summation. 637 * @param S BigDecimal. 638 * @return this+S. 639 */ 640 public BigDecimal sum(BigDecimal S) { 641 return new BigDecimal(val.add(S.val, context)); 642 } 643 644 645 /** 646 * BigDecimal parse from String. 647 * @param s String. 648 * @return Biginteger from s. 649 */ 650 public BigDecimal parse(String s) { 651 return new BigDecimal(s, context); 652 } 653 654 655 /** 656 * BigDecimal parse from Reader. 657 * @param r Reader. 658 * @return next Biginteger from r. 659 */ 660 public BigDecimal parse(Reader r) { 661 return parse(StringUtil.nextString(r)); 662 } 663 664}