| GNU Classpath (0.95) | |
| Frames | No Frames |
1: /* java.math.BigDecimal -- Arbitrary precision decimals. 2: Copyright (C) 1999, 2000, 2001, 2003, 2005, 2006 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: package java.math; 39: 40: public class BigDecimal extends Number implements Comparable<BigDecimal> 41: { 42: private BigInteger intVal; 43: private int scale; 44: private int precision = 0; 45: private static final long serialVersionUID = 6108874887143696463L; 46: 47: /** 48: * The constant zero as a BigDecimal with scale zero. 49: * @since 1.5 50: */ 51: public static final BigDecimal ZERO = 52: new BigDecimal (BigInteger.ZERO, 0); 53: 54: /** 55: * The constant one as a BigDecimal with scale zero. 56: * @since 1.5 57: */ 58: public static final BigDecimal ONE = 59: new BigDecimal (BigInteger.ONE, 0); 60: 61: /** 62: * The constant ten as a BigDecimal with scale zero. 63: * @since 1.5 64: */ 65: public static final BigDecimal TEN = 66: new BigDecimal (BigInteger.TEN, 0); 67: 68: public static final int ROUND_UP = 0; 69: public static final int ROUND_DOWN = 1; 70: public static final int ROUND_CEILING = 2; 71: public static final int ROUND_FLOOR = 3; 72: public static final int ROUND_HALF_UP = 4; 73: public static final int ROUND_HALF_DOWN = 5; 74: public static final int ROUND_HALF_EVEN = 6; 75: public static final int ROUND_UNNECESSARY = 7; 76: 77: /** 78: * Constructs a new BigDecimal whose unscaled value is val and whose 79: * scale is zero. 80: * @param val the value of the new BigDecimal 81: * @since 1.5 82: */ 83: public BigDecimal (int val) 84: { 85: this.intVal = BigInteger.valueOf(val); 86: this.scale = 0; 87: } 88: 89: /** 90: * Constructs a BigDecimal using the BigDecimal(int) constructor and then 91: * rounds according to the MathContext. 92: * @param val the value for the initial (unrounded) BigDecimal 93: * @param mc the MathContext specifying the rounding 94: * @throws ArithmeticException if the result is inexact but the rounding type 95: * is RoundingMode.UNNECESSARY 96: * @since 1.5 97: */ 98: public BigDecimal (int val, MathContext mc) 99: { 100: this (val); 101: if (mc.getPrecision() != 0) 102: { 103: BigDecimal result = this.round(mc); 104: this.intVal = result.intVal; 105: this.scale = result.scale; 106: this.precision = result.precision; 107: } 108: } 109: 110: /** 111: * Constructs a new BigDecimal whose unscaled value is val and whose 112: * scale is zero. 113: * @param val the value of the new BigDecimal 114: */ 115: public BigDecimal (long val) 116: { 117: this.intVal = BigInteger.valueOf(val); 118: this.scale = 0; 119: } 120: 121: /** 122: * Constructs a BigDecimal from the long in the same way as BigDecimal(long) 123: * and then rounds according to the MathContext. 124: * @param val the long from which we create the initial BigDecimal 125: * @param mc the MathContext that specifies the rounding behaviour 126: * @throws ArithmeticException if the result is inexact but the rounding type 127: * is RoundingMode.UNNECESSARY 128: * @since 1.5 129: */ 130: public BigDecimal (long val, MathContext mc) 131: { 132: this(val); 133: if (mc.getPrecision() != 0) 134: { 135: BigDecimal result = this.round(mc); 136: this.intVal = result.intVal; 137: this.scale = result.scale; 138: this.precision = result.precision; 139: } 140: } 141: 142: /** 143: * Constructs a BigDecimal whose value is given by num rounded according to 144: * mc. Since num is already a BigInteger, the rounding refers only to the 145: * precision setting in mc, if mc.getPrecision() returns an int lower than 146: * the number of digits in num, then rounding is necessary. 147: * @param num the unscaledValue, before rounding 148: * @param mc the MathContext that specifies the precision 149: * @throws ArithmeticException if the result is inexact but the rounding type 150: * is RoundingMode.UNNECESSARY 151: * * @since 1.5 152: */ 153: public BigDecimal (BigInteger num, MathContext mc) 154: { 155: this (num, 0); 156: if (mc.getPrecision() != 0) 157: { 158: BigDecimal result = this.round(mc); 159: this.intVal = result.intVal; 160: this.scale = result.scale; 161: this.precision = result.precision; 162: } 163: } 164: 165: /** 166: * Constructs a BigDecimal from the String val according to the same 167: * rules as the BigDecimal(String) constructor and then rounds 168: * according to the MathContext mc. 169: * @param val the String from which we construct the initial BigDecimal 170: * @param mc the MathContext that specifies the rounding 171: * @throws ArithmeticException if the result is inexact but the rounding type 172: * is RoundingMode.UNNECESSARY 173: * @since 1.5 174: */ 175: public BigDecimal (String val, MathContext mc) 176: { 177: this (val); 178: if (mc.getPrecision() != 0) 179: { 180: BigDecimal result = this.round(mc); 181: this.intVal = result.intVal; 182: this.scale = result.scale; 183: this.precision = result.precision; 184: } 185: } 186: 187: /** 188: * Constructs a BigDecimal whose unscaled value is num and whose 189: * scale is zero. 190: * @param num the value of the new BigDecimal 191: */ 192: public BigDecimal (BigInteger num) 193: { 194: this (num, 0); 195: } 196: 197: /** 198: * Constructs a BigDecimal whose unscaled value is num and whose 199: * scale is scale. 200: * @param num 201: * @param scale 202: */ 203: public BigDecimal (BigInteger num, int scale) 204: { 205: this.intVal = num; 206: this.scale = scale; 207: } 208: 209: /** 210: * Constructs a BigDecimal using the BigDecimal(BigInteger, int) 211: * constructor and then rounds according to the MathContext. 212: * @param num the unscaled value of the unrounded BigDecimal 213: * @param scale the scale of the unrounded BigDecimal 214: * @param mc the MathContext specifying the rounding 215: * @throws ArithmeticException if the result is inexact but the rounding type 216: * is RoundingMode.UNNECESSARY 217: * @since 1.5 218: */ 219: public BigDecimal (BigInteger num, int scale, MathContext mc) 220: { 221: this (num, scale); 222: if (mc.getPrecision() != 0) 223: { 224: BigDecimal result = this.round(mc); 225: this.intVal = result.intVal; 226: this.scale = result.scale; 227: this.precision = result.precision; 228: } 229: } 230: 231: /** 232: * Constructs a BigDecimal in the same way as BigDecimal(double) and then 233: * rounds according to the MathContext. 234: * @param num the double from which the initial BigDecimal is created 235: * @param mc the MathContext that specifies the rounding behaviour 236: * @throws ArithmeticException if the result is inexact but the rounding type 237: * is RoundingMode.UNNECESSARY 238: * @since 1.5 239: */ 240: public BigDecimal (double num, MathContext mc) 241: { 242: this (num); 243: if (mc.getPrecision() != 0) 244: { 245: BigDecimal result = this.round(mc); 246: this.intVal = result.intVal; 247: this.scale = result.scale; 248: this.precision = result.precision; 249: } 250: } 251: 252: public BigDecimal (double num) throws NumberFormatException 253: { 254: if (Double.isInfinite (num) || Double.isNaN (num)) 255: throw new NumberFormatException ("invalid argument: " + num); 256: // Note we can't convert NUM to a String and then use the 257: // String-based constructor. The BigDecimal documentation makes 258: // it clear that the two constructors work differently. 259: 260: final int mantissaBits = 52; 261: final int exponentBits = 11; 262: final long mantMask = (1L << mantissaBits) - 1; 263: final long expMask = (1L << exponentBits) - 1; 264: 265: long bits = Double.doubleToLongBits (num); 266: long mantissa = bits & mantMask; 267: long exponent = (bits >>> mantissaBits) & expMask; 268: boolean denormal = exponent == 0; 269: 270: // Correct the exponent for the bias. 271: exponent -= denormal ? 1022 : 1023; 272: 273: // Now correct the exponent to account for the bits to the right 274: // of the decimal. 275: exponent -= mantissaBits; 276: // Ordinary numbers have an implied leading `1' bit. 277: if (! denormal) 278: mantissa |= (1L << mantissaBits); 279: 280: // Shave off factors of 10. 281: while (exponent < 0 && (mantissa & 1) == 0) 282: { 283: ++exponent; 284: mantissa >>= 1; 285: } 286: 287: intVal = BigInteger.valueOf (bits < 0 ? - mantissa : mantissa); 288: if (exponent < 0) 289: { 290: // We have MANTISSA * 2 ^ (EXPONENT). 291: // Since (1/2)^N == 5^N * 10^-N we can easily convert this 292: // into a power of 10. 293: scale = (int) (- exponent); 294: BigInteger mult = BigInteger.valueOf (5).pow (scale); 295: intVal = intVal.multiply (mult); 296: } 297: else 298: { 299: intVal = intVal.shiftLeft ((int) exponent); 300: scale = 0; 301: } 302: } 303: 304: /** 305: * Constructs a BigDecimal from the char subarray and rounding 306: * according to the MathContext. 307: * @param in the char array 308: * @param offset the start of the subarray 309: * @param len the length of the subarray 310: * @param mc the MathContext for rounding 311: * @throws NumberFormatException if the char subarray is not a valid 312: * BigDecimal representation 313: * @throws ArithmeticException if the result is inexact but the rounding 314: * mode is RoundingMode.UNNECESSARY 315: * @since 1.5 316: */ 317: public BigDecimal(char[] in, int offset, int len, MathContext mc) 318: { 319: this(in, offset, len); 320: // If mc has precision other than zero then we must round. 321: if (mc.getPrecision() != 0) 322: { 323: BigDecimal temp = this.round(mc); 324: this.intVal = temp.intVal; 325: this.scale = temp.scale; 326: this.precision = temp.precision; 327: } 328: } 329: 330: /** 331: * Constructs a BigDecimal from the char array and rounding according 332: * to the MathContext. 333: * @param in the char array 334: * @param mc the MathContext 335: * @throws NumberFormatException if <code>in</code> is not a valid BigDecimal 336: * representation 337: * @throws ArithmeticException if the result is inexact but the rounding mode 338: * is RoundingMode.UNNECESSARY 339: * @since 1.5 340: */ 341: public BigDecimal(char[] in, MathContext mc) 342: { 343: this(in, 0, in.length); 344: // If mc has precision other than zero then we must round. 345: if (mc.getPrecision() != 0) 346: { 347: BigDecimal temp = this.round(mc); 348: this.intVal = temp.intVal; 349: this.scale = temp.scale; 350: this.precision = temp.precision; 351: } 352: } 353: 354: /** 355: * Constructs a BigDecimal from the given char array, accepting the same 356: * sequence of characters as the BigDecimal(String) constructor. 357: * @param in the char array 358: * @throws NumberFormatException if <code>in</code> is not a valid BigDecimal 359: * representation 360: * @since 1.5 361: */ 362: public BigDecimal(char[] in) 363: { 364: this(in, 0, in.length); 365: } 366: 367: /** 368: * Constructs a BigDecimal from a char subarray, accepting the same sequence 369: * of characters as the BigDecimal(String) constructor. 370: * @param in the char array 371: * @param offset the start of the subarray 372: * @param len the length of the subarray 373: * @throws NumberFormatException if <code>in</code> is not a valid 374: * BigDecimal representation. 375: * @since 1.5 376: */ 377: public BigDecimal(char[] in, int offset, int len) 378: { 379: // start is the index into the char array where the significand starts 380: int start = offset; 381: // end is one greater than the index of the last character used 382: int end = offset + len; 383: // point is the index into the char array where the exponent starts 384: // (or, if there is no exponent, this is equal to end) 385: int point = offset; 386: // dot is the index into the char array where the decimal point is 387: // found, or -1 if there is no decimal point 388: int dot = -1; 389: 390: // The following examples show what these variables mean. Note that 391: // point and dot don't yet have the correct values, they will be 392: // properly assigned in a loop later on in this method. 393: // 394: // Example 1 395: // 396: // + 1 0 2 . 4 6 9 397: // __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ 398: // 399: // offset = 2, len = 8, start = 3, dot = 6, point = end = 10 400: // 401: // Example 2 402: // 403: // + 2 3 4 . 6 1 3 E - 1 404: // __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ 405: // 406: // offset = 2, len = 11, start = 3, dot = 6, point = 10, end = 13 407: // 408: // Example 3 409: // 410: // - 1 2 3 4 5 e 7 411: // __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ 412: // 413: // offset = 2, len = 8, start = 3, dot = -1, point = 8, end = 10 414: 415: // Determine the sign of the number. 416: boolean negative = false; 417: if (in[offset] == '+') 418: { 419: ++start; 420: ++point; 421: } 422: else if (in[offset] == '-') 423: { 424: ++start; 425: ++point; 426: negative = true; 427: } 428: 429: // Check each character looking for the decimal point and the 430: // start of the exponent. 431: while (point < end) 432: { 433: char c = in[point]; 434: if (c == '.') 435: { 436: // If dot != -1 then we've seen more than one decimal point. 437: if (dot != -1) 438: throw new NumberFormatException("multiple `.'s in number"); 439: dot = point; 440: } 441: // Break when we reach the start of the exponent. 442: else if (c == 'e' || c == 'E') 443: break; 444: // Throw an exception if the character was not a decimal or an 445: // exponent and is not a digit. 446: else if (!Character.isDigit(c)) 447: throw new NumberFormatException("unrecognized character at " + point 448: + ": " + c); 449: ++point; 450: } 451: 452: // val is a StringBuilder from which we'll create a BigInteger 453: // which will be the unscaled value for this BigDecimal 454: StringBuilder val = new StringBuilder(point - start - 1); 455: if (dot != -1) 456: { 457: // If there was a decimal we must combine the two parts that 458: // contain only digits and we must set the scale properly. 459: val.append(in, start, dot - start); 460: val.append(in, dot + 1, point - dot - 1); 461: scale = point - 1 - dot; 462: } 463: else 464: { 465: // If there was no decimal then the unscaled value is just the number 466: // formed from all the digits and the scale is zero. 467: val.append(in, start, point - start); 468: scale = 0; 469: } 470: if (val.length() == 0) 471: throw new NumberFormatException("no digits seen"); 472: 473: // Prepend a negative sign if necessary. 474: if (negative) 475: val.insert(0, '-'); 476: intVal = new BigInteger(val.toString()); 477: 478: // Now parse exponent. 479: // If point < end that means we broke out of the previous loop when we 480: // saw an 'e' or an 'E'. 481: if (point < end) 482: { 483: point++; 484: // Ignore a '+' sign. 485: if (in[point] == '+') 486: point++; 487: 488: // Throw an exception if there were no digits found after the 'e' 489: // or 'E'. 490: if (point >= end) 491: throw new NumberFormatException("no exponent following e or E"); 492: 493: try 494: { 495: // Adjust the scale according to the exponent. 496: // Remember that the value of a BigDecimal is 497: // unscaledValue x Math.pow(10, -scale) 498: scale -= Integer.parseInt(new String(in, point, end - point)); 499: } 500: catch (NumberFormatException ex) 501: { 502: throw new NumberFormatException("malformed exponent"); 503: } 504: } 505: } 506: 507: public BigDecimal (String num) throws NumberFormatException 508: { 509: int len = num.length(); 510: int start = 0, point = 0; 511: int dot = -1; 512: boolean negative = false; 513: if (num.charAt(0) == '+') 514: { 515: ++start; 516: ++point; 517: } 518: else if (num.charAt(0) == '-') 519: { 520: ++start; 521: ++point; 522: negative = true; 523: } 524: 525: while (point < len) 526: { 527: char c = num.charAt (point); 528: if (c == '.') 529: { 530: if (dot >= 0) 531: throw new NumberFormatException ("multiple `.'s in number"); 532: dot = point; 533: } 534: else if (c == 'e' || c == 'E') 535: break; 536: else if (Character.digit (c, 10) < 0) 537: throw new NumberFormatException ("unrecognized character: " + c); 538: ++point; 539: } 540: 541: String val; 542: if (dot >= 0) 543: { 544: val = num.substring (start, dot) + num.substring (dot + 1, point); 545: scale = point - 1 - dot; 546: } 547: else 548: { 549: val = num.substring (start, point); 550: scale = 0; 551: } 552: if (val.length () == 0) 553: throw new NumberFormatException ("no digits seen"); 554: 555: if (negative) 556: val = "-" + val; 557: intVal = new BigInteger (val); 558: 559: // Now parse exponent. 560: if (point < len) 561: { 562: point++; 563: if (num.charAt(point) == '+') 564: point++; 565: 566: if (point >= len ) 567: throw new NumberFormatException ("no exponent following e or E"); 568: 569: try 570: { 571: scale -= Integer.parseInt (num.substring (point)); 572: } 573: catch (NumberFormatException ex) 574: { 575: throw new NumberFormatException ("malformed exponent"); 576: } 577: } 578: } 579: 580: public static BigDecimal valueOf (long val) 581: { 582: return valueOf (val, 0); 583: } 584: 585: public static BigDecimal valueOf (long val, int scale) 586: throws NumberFormatException 587: { 588: if ((scale == 0) && ((int)val == val)) 589: switch ((int) val) 590: { 591: case 0: 592: return ZERO; 593: case 1: 594: return ONE; 595: } 596: 597: return new BigDecimal (BigInteger.valueOf (val), scale); 598: } 599: 600: public BigDecimal add (BigDecimal val) 601: { 602: // For addition, need to line up decimals. Note that the movePointRight 603: // method cannot be used for this as it might return a BigDecimal with 604: // scale == 0 instead of the scale we need. 605: BigInteger op1 = intVal; 606: BigInteger op2 = val.intVal; 607: if (scale < val.scale) 608: op1 = op1.multiply (BigInteger.TEN.pow (val.scale - scale)); 609: else if (scale > val.scale) 610: op2 = op2.multiply (BigInteger.TEN.pow (scale - val.scale)); 611: 612: return new BigDecimal (op1.add (op2), Math.max (scale, val.scale)); 613: } 614: 615: /** 616: * Returns a BigDecimal whose value is found first by calling the 617: * method add(val) and then by rounding according to the MathContext mc. 618: * @param val the augend 619: * @param mc the MathContext for rounding 620: * @throws ArithmeticException if the value is inexact but the rounding is 621: * RoundingMode.UNNECESSARY 622: * @return <code>this</code> + <code>val</code>, rounded if need be 623: * @since 1.5 624: */ 625: public BigDecimal add (BigDecimal val, MathContext mc) 626: { 627: return add(val).round(mc); 628: } 629: 630: public BigDecimal subtract (BigDecimal val) 631: { 632: return this.add(val.negate()); 633: } 634: 635: /** 636: * Returns a BigDecimal whose value is found first by calling the 637: * method subtract(val) and then by rounding according to the MathContext mc. 638: * @param val the subtrahend 639: * @param mc the MathContext for rounding 640: * @throws ArithmeticException if the value is inexact but the rounding is 641: * RoundingMode.UNNECESSARY 642: * @return <code>this</code> - <code>val</code>, rounded if need be 643: * @since 1.5 644: */ 645: public BigDecimal subtract (BigDecimal val, MathContext mc) 646: { 647: return subtract(val).round(mc); 648: } 649: 650: public BigDecimal multiply (BigDecimal val) 651: { 652: return new BigDecimal (intVal.multiply (val.intVal), scale + val.scale); 653: } 654: 655: /** 656: * Returns a BigDecimal whose value is (this x val) before it is rounded 657: * according to the MathContext mc. 658: * @param val the multiplicand 659: * @param mc the MathContext for rounding 660: * @return a new BigDecimal with value approximately (this x val) 661: * @throws ArithmeticException if the value is inexact but the rounding mode 662: * is RoundingMode.UNNECESSARY 663: * @since 1.5 664: */ 665: public BigDecimal multiply (BigDecimal val, MathContext mc) 666: { 667: return multiply(val).round(mc); 668: } 669: 670: public BigDecimal divide (BigDecimal val, int roundingMode) 671: throws ArithmeticException, IllegalArgumentException 672: { 673: return divide (val, scale, roundingMode); 674: } 675: 676: /** 677: * Returns a BigDecimal whose value is (this / val), with the specified scale 678: * and rounding according to the RoundingMode 679: * @param val the divisor 680: * @param scale the scale of the BigDecimal returned 681: * @param roundingMode the rounding mode to use 682: * @return a BigDecimal whose value is approximately (this / val) 683: * @throws ArithmeticException if divisor is zero or the rounding mode is 684: * UNNECESSARY but the specified scale cannot represent the value exactly 685: * @since 1.5 686: */ 687: public BigDecimal divide(BigDecimal val, 688: int scale, RoundingMode roundingMode) 689: { 690: return divide (val, scale, roundingMode.ordinal()); 691: } 692: 693: /** 694: * Returns a BigDecimal whose value is (this / val) rounded according to the 695: * RoundingMode 696: * @param val the divisor 697: * @param roundingMode the rounding mode to use 698: * @return a BigDecimal whose value is approximately (this / val) 699: * @throws ArithmeticException if divisor is zero or the rounding mode is 700: * UNNECESSARY but the specified scale cannot represent the value exactly 701: */ 702: public BigDecimal divide (BigDecimal val, RoundingMode roundingMode) 703: { 704: return divide (val, scale, roundingMode.ordinal()); 705: } 706: 707: public BigDecimal divide(BigDecimal val, int newScale, int roundingMode) 708: throws ArithmeticException, IllegalArgumentException 709: { 710: if (roundingMode < 0 || roundingMode > 7) 711: throw 712: new IllegalArgumentException("illegal rounding mode: " + roundingMode); 713: 714: if (intVal.signum () == 0) // handle special case of 0.0/0.0 715: return newScale == 0 ? ZERO : new BigDecimal (ZERO.intVal, newScale); 716: 717: // Ensure that pow gets a non-negative value. 718: BigInteger valIntVal = val.intVal; 719: int power = newScale - (scale - val.scale); 720: if (power < 0) 721: { 722: // Effectively increase the scale of val to avoid an 723: // ArithmeticException for a negative power. 724: valIntVal = valIntVal.multiply (BigInteger.TEN.pow (-power)); 725: power = 0; 726: } 727: 728: BigInteger dividend = intVal.multiply (BigInteger.TEN.pow (power)); 729: 730: BigInteger parts[] = dividend.divideAndRemainder (valIntVal); 731: 732: BigInteger unrounded = parts[0]; 733: if (parts[1].signum () == 0) // no remainder, no rounding necessary 734: return new BigDecimal (unrounded, newScale); 735: 736: if (roundingMode == ROUND_UNNECESSARY) 737: throw new ArithmeticException ("Rounding necessary"); 738: 739: int sign = intVal.signum () * valIntVal.signum (); 740: 741: if (roundingMode == ROUND_CEILING) 742: roundingMode = (sign > 0) ? ROUND_UP : ROUND_DOWN; 743: else if (roundingMode == ROUND_FLOOR) 744: roundingMode = (sign < 0) ? ROUND_UP : ROUND_DOWN; 745: else 746: { 747: // half is -1 if remainder*2 < positive intValue (*power), 0 if equal, 748: // 1 if >. This implies that the remainder to round is less than, 749: // equal to, or greater than half way to the next digit. 750: BigInteger posRemainder 751: = parts[1].signum () < 0 ? parts[1].negate() : parts[1]; 752: valIntVal = valIntVal.signum () < 0 ? valIntVal.negate () : valIntVal; 753: int half = posRemainder.shiftLeft(1).compareTo(valIntVal); 754: 755: switch(roundingMode) 756: { 757: case ROUND_HALF_UP: 758: roundingMode = (half < 0) ? ROUND_DOWN : ROUND_UP; 759: break; 760: case ROUND_HALF_DOWN: 761: roundingMode = (half > 0) ? ROUND_UP : ROUND_DOWN; 762: break; 763: case ROUND_HALF_EVEN: 764: if (half < 0) 765: roundingMode = ROUND_DOWN; 766: else if (half > 0) 767: roundingMode = ROUND_UP; 768: else if (unrounded.testBit(0)) // odd, then ROUND_HALF_UP 769: roundingMode = ROUND_UP; 770: else // even, ROUND_HALF_DOWN 771: roundingMode = ROUND_DOWN; 772: break; 773: } 774: } 775: 776: if (roundingMode == ROUND_UP) 777: unrounded = unrounded.add (BigInteger.valueOf (sign > 0 ? 1 : -1)); 778: 779: // roundingMode == ROUND_DOWN 780: return new BigDecimal (unrounded, newScale); 781: } 782: 783: /** 784: * Performs division, if the resulting quotient requires rounding 785: * (has a nonterminating decimal expansion), 786: * an ArithmeticException is thrown. 787: * #see divide(BigDecimal, int, int) 788: * @since 1.5 789: */ 790: public BigDecimal divide(BigDecimal divisor) 791: throws ArithmeticException, IllegalArgumentException 792: { 793: return divide(divisor, scale, ROUND_UNNECESSARY); 794: } 795: 796: /** 797: * Returns a BigDecimal whose value is the remainder in the quotient 798: * this / val. This is obtained by 799: * subtract(divideToIntegralValue(val).multiply(val)). 800: * @param val the divisor 801: * @return a BigDecimal whose value is the remainder 802: * @throws ArithmeticException if val == 0 803: * @since 1.5 804: */ 805: public BigDecimal remainder(BigDecimal val) 806: { 807: return subtract(divideToIntegralValue(val).multiply(val)); 808: } 809: 810: /** 811: * Returns a BigDecimal array, the first element of which is the integer part 812: * of this / val, and the second element of which is the remainder of 813: * that quotient. 814: * @param val the divisor