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: import gnu.java.lang.CPStringBuilder; 41: 42: public class BigDecimal extends Number implements Comparable<BigDecimal> 43: { 44: private BigInteger intVal; 45: private int scale; 46: private int precision = 0; 47: private static final long serialVersionUID = 6108874887143696463L; 48: 49: /** 50: * The constant zero as a BigDecimal with scale zero. 51: * @since 1.5 52: */ 53: public static final BigDecimal ZERO = 54: new BigDecimal (BigInteger.ZERO, 0); 55: 56: /** 57: * The constant one as a BigDecimal with scale zero. 58: * @since 1.5 59: */ 60: public static final BigDecimal ONE = 61: new BigDecimal (BigInteger.ONE, 0); 62: 63: /** 64: * The constant ten as a BigDecimal with scale zero. 65: * @since 1.5 66: */ 67: public static final BigDecimal TEN = 68: new BigDecimal (BigInteger.TEN, 0); 69: 70: public static final int ROUND_UP = 0; 71: public static final int ROUND_DOWN = 1; 72: public static final int ROUND_CEILING = 2; 73: public static final int ROUND_FLOOR = 3; 74: public static final int ROUND_HALF_UP = 4; 75: public static final int ROUND_HALF_DOWN = 5; 76: public static final int ROUND_HALF_EVEN = 6; 77: public static final int ROUND_UNNECESSARY = 7; 78: 79: /** 80: * Constructs a new BigDecimal whose unscaled value is val and whose 81: * scale is zero. 82: * @param val the value of the new BigDecimal 83: * @since 1.5 84: */ 85: public BigDecimal (int val) 86: { 87: this.intVal = BigInteger.valueOf(val); 88: this.scale = 0; 89: } 90: 91: /** 92: * Constructs a BigDecimal using the BigDecimal(int) constructor and then 93: * rounds according to the MathContext. 94: * @param val the value for the initial (unrounded) BigDecimal 95: * @param mc the MathContext specifying the rounding 96: * @throws ArithmeticException if the result is inexact but the rounding type 97: * is RoundingMode.UNNECESSARY 98: * @since 1.5 99: */ 100: public BigDecimal (int val, MathContext mc) 101: { 102: this (val); 103: if (mc.getPrecision() != 0) 104: { 105: BigDecimal result = this.round(mc); 106: this.intVal = result.intVal; 107: this.scale = result.scale; 108: this.precision = result.precision; 109: } 110: } 111: 112: /** 113: * Constructs a new BigDecimal whose unscaled value is val and whose 114: * scale is zero. 115: * @param val the value of the new BigDecimal 116: */ 117: public BigDecimal (long val) 118: { 119: this.intVal = BigInteger.valueOf(val); 120: this.scale = 0; 121: } 122: 123: /** 124: * Constructs a BigDecimal from the long in the same way as BigDecimal(long) 125: * and then rounds according to the MathContext. 126: * @param val the long from which we create the initial BigDecimal 127: * @param mc the MathContext that specifies the rounding behaviour 128: * @throws ArithmeticException if the result is inexact but the rounding type 129: * is RoundingMode.UNNECESSARY 130: * @since 1.5 131: */ 132: public BigDecimal (long val, MathContext mc) 133: { 134: this(val); 135: if (mc.getPrecision() != 0) 136: { 137: BigDecimal result = this.round(mc); 138: this.intVal = result.intVal; 139: this.scale = result.scale; 140: this.precision = result.precision; 141: } 142: } 143: 144: /** 145: * Constructs a BigDecimal whose value is given by num rounded according to 146: * mc. Since num is already a BigInteger, the rounding refers only to the 147: * precision setting in mc, if mc.getPrecision() returns an int lower than 148: * the number of digits in num, then rounding is necessary. 149: * @param num the unscaledValue, before rounding 150: * @param mc the MathContext that specifies the precision 151: * @throws ArithmeticException if the result is inexact but the rounding type 152: * is RoundingMode.UNNECESSARY 153: * * @since 1.5 154: */ 155: public BigDecimal (BigInteger num, MathContext mc) 156: { 157: this (num, 0); 158: if (mc.getPrecision() != 0) 159: { 160: BigDecimal result = this.round(mc); 161: this.intVal = result.intVal; 162: this.scale = result.scale; 163: this.precision = result.precision; 164: } 165: } 166: 167: /** 168: * Constructs a BigDecimal from the String val according to the same 169: * rules as the BigDecimal(String) constructor and then rounds 170: * according to the MathContext mc. 171: * @param val the String from which we construct the initial BigDecimal 172: * @param mc the MathContext that specifies the rounding 173: * @throws ArithmeticException if the result is inexact but the rounding type 174: * is RoundingMode.UNNECESSARY 175: * @since 1.5 176: */ 177: public BigDecimal (String val, MathContext mc) 178: { 179: this (val); 180: if (mc.getPrecision() != 0) 181: { 182: BigDecimal result = this.round(mc); 183: this.intVal = result.intVal; 184: this.scale = result.scale; 185: this.precision = result.precision; 186: } 187: } 188: 189: /** 190: * Constructs a BigDecimal whose unscaled value is num and whose 191: * scale is zero. 192: * @param num the value of the new BigDecimal 193: */ 194: public BigDecimal (BigInteger num) 195: { 196: this (num, 0); 197: } 198: 199: /** 200: * Constructs a BigDecimal whose unscaled value is num and whose 201: * scale is scale. 202: * @param num 203: * @param scale 204: */ 205: public BigDecimal (BigInteger num, int scale) 206: { 207: this.intVal = num; 208: this.scale = scale; 209: } 210: 211: /** 212: * Constructs a BigDecimal using the BigDecimal(BigInteger, int) 213: * constructor and then rounds according to the MathContext. 214: * @param num the unscaled value of the unrounded BigDecimal 215: * @param scale the scale of the unrounded BigDecimal 216: * @param mc the MathContext specifying the rounding 217: * @throws ArithmeticException if the result is inexact but the rounding type 218: * is RoundingMode.UNNECESSARY 219: * @since 1.5 220: */ 221: public BigDecimal (BigInteger num, int scale, MathContext mc) 222: { 223: this (num, scale); 224: if (mc.getPrecision() != 0) 225: { 226: BigDecimal result = this.round(mc); 227: this.intVal = result.intVal; 228: this.scale = result.scale; 229: this.precision = result.precision; 230: } 231: } 232: 233: /** 234: * Constructs a BigDecimal in the same way as BigDecimal(double) and then 235: * rounds according to the MathContext. 236: * @param num the double from which the initial BigDecimal is created 237: * @param mc the MathContext that specifies the rounding behaviour 238: * @throws ArithmeticException if the result is inexact but the rounding type 239: * is RoundingMode.UNNECESSARY 240: * @since 1.5 241: */ 242: public BigDecimal (double num, MathContext mc) 243: { 244: this (num); 245: if (mc.getPrecision() != 0) 246: { 247: BigDecimal result = this.round(mc); 248: this.intVal = result.intVal; 249: this.scale = result.scale; 250: this.precision = result.precision; 251: } 252: } 253: 254: public BigDecimal (double num) throws NumberFormatException 255: { 256: if (Double.isInfinite (num) || Double.isNaN (num)) 257: throw new NumberFormatException ("invalid argument: " + num); 258: // Note we can't convert NUM to a String and then use the 259: // String-based constructor. The BigDecimal documentation makes 260: // it clear that the two constructors work differently. 261: 262: final int mantissaBits = 52; 263: final int exponentBits = 11; 264: final long mantMask = (1L << mantissaBits) - 1; 265: final long expMask = (1L << exponentBits) - 1; 266: 267: long bits = Double.doubleToLongBits (num); 268: long mantissa = bits & mantMask; 269: long exponent = (bits >>> mantissaBits) & expMask; 270: boolean denormal = exponent == 0; 271: 272: // Correct the exponent for the bias. 273: exponent -= denormal ? 1022 : 1023; 274: 275: // Now correct the exponent to account for the bits to the right 276: // of the decimal. 277: exponent -= mantissaBits; 278: // Ordinary numbers have an implied leading `1' bit. 279: if (! denormal) 280: mantissa |= (1L << mantissaBits); 281: 282: // Shave off factors of 10. 283: while (exponent < 0 && (mantissa & 1) == 0) 284: { 285: ++exponent; 286: mantissa >>= 1; 287: } 288: 289: intVal = BigInteger.valueOf (bits < 0 ? - mantissa : mantissa); 290: if (exponent < 0) 291: { 292: // We have MANTISSA * 2 ^ (EXPONENT). 293: // Since (1/2)^N == 5^N * 10^-N we can easily convert this 294: // into a power of 10. 295: scale = (int) (- exponent); 296: BigInteger mult = BigInteger.valueOf (5).pow (scale); 297: intVal = intVal.multiply (mult); 298: } 299: else 300: { 301: intVal = intVal.shiftLeft ((int) exponent); 302: scale = 0; 303: } 304: } 305: 306: /** 307: * Constructs a BigDecimal from the char subarray and rounding 308: * according to the MathContext. 309: * @param in the char array 310: * @param offset the start of the subarray 311: * @param len the length of the subarray 312: * @param mc the MathContext for rounding 313: * @throws NumberFormatException if the char subarray is not a valid 314: * BigDecimal representation 315: * @throws ArithmeticException if the result is inexact but the rounding 316: * mode is RoundingMode.UNNECESSARY 317: * @since 1.5 318: */ 319: public BigDecimal(char[] in, int offset, int len, MathContext mc) 320: { 321: this(in, offset, len); 322: // If mc has precision other than zero then we must round. 323: if (mc.getPrecision() != 0) 324: { 325: BigDecimal temp = this.round(mc); 326: this.intVal = temp.intVal; 327: this.scale = temp.scale; 328: this.precision = temp.precision; 329: } 330: } 331: 332: /** 333: * Constructs a BigDecimal from the char array and rounding according 334: * to the MathContext. 335: * @param in the char array 336: * @param mc the MathContext 337: * @throws NumberFormatException if <code>in</code> is not a valid BigDecimal 338: * representation 339: * @throws ArithmeticException if the result is inexact but the rounding mode 340: * is RoundingMode.UNNECESSARY 341: * @since 1.5 342: */ 343: public BigDecimal(char[] in, MathContext mc) 344: { 345: this(in, 0, in.length); 346: // If mc has precision other than zero then we must round. 347: if (mc.getPrecision() != 0) 348: { 349: BigDecimal temp = this.round(mc); 350: this.intVal = temp.intVal; 351: this.scale = temp.scale; 352: this.precision = temp.precision; 353: } 354: } 355: 356: /** 357: * Constructs a BigDecimal from the given char array, accepting the same 358: * sequence of characters as the BigDecimal(String) constructor. 359: * @param in the char array 360: * @throws NumberFormatException if <code>in</code> is not a valid BigDecimal 361: * representation 362: * @since 1.5 363: */ 364: public BigDecimal(char[] in) 365: { 366: this(in, 0, in.length); 367: } 368: 369: /** 370: * Constructs a BigDecimal from a char subarray, accepting the same sequence 371: * of characters as the BigDecimal(String) constructor. 372: * @param in the char array 373: * @param offset the start of the subarray 374: * @param len the length of the subarray 375: * @throws NumberFormatException if <code>in</code> is not a valid 376: * BigDecimal representation. 377: * @since 1.5 378: */ 379: public BigDecimal(char[] in, int offset, int len) 380: { 381: // start is the index into the char array where the significand starts 382: int start = offset; 383: // end is one greater than the index of the last character used 384: int end = offset + len; 385: // point is the index into the char array where the exponent starts 386: // (or, if there is no exponent, this is equal to end) 387: int point = offset; 388: // dot is the index into the char array where the decimal point is 389: // found, or -1 if there is no decimal point 390: int dot = -1; 391: 392: // The following examples show what these variables mean. Note that 393: // point and dot don't yet have the correct values, they will be 394: // properly assigned in a loop later on in this method. 395: // 396: // Example 1 397: // 398: // + 1 0 2 . 4 6 9 399: // __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ 400: // 401: // offset = 2, len = 8, start = 3, dot = 6, point = end = 10 402: // 403: // Example 2 404: // 405: // + 2 3 4 . 6 1 3 E - 1 406: // __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ 407: // 408: // offset = 2, len = 11, start = 3, dot = 6, point = 10, end = 13 409: // 410: // Example 3 411: // 412: // - 1 2 3 4 5 e 7 413: // __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ 414: // 415: // offset = 2, len = 8, start = 3, dot = -1, point = 8, end = 10 416: 417: // Determine the sign of the number. 418: boolean negative = false; 419: if (in[offset] == '+') 420: { 421: ++start; 422: ++point; 423: } 424: else if (in[offset] == '-') 425: { 426: ++start; 427: ++point; 428: negative = true; 429: } 430: 431: // Check each character looking for the decimal point and the 432: // start of the exponent. 433: while (point < end) 434: { 435: char c = in[point]; 436: if (c == '.') 437: { 438: // If dot != -1 then we've seen more than one decimal point. 439: if (dot != -1) 440: throw new NumberFormatException("multiple `.'s in number"); 441: dot = point; 442: } 443: // Break when we reach the start of the exponent. 444: else if (c == 'e' || c == 'E') 445: break; 446: // Throw an exception if the character was not a decimal or an 447: // exponent and is not a digit. 448: else if (!Character.isDigit(c)) 449: throw new NumberFormatException("unrecognized character at " + point 450: + ": " + c); 451: ++point; 452: } 453: 454: // val is a StringBuilder from which we'll create a BigInteger 455: // which will be the unscaled value for this BigDecimal 456: CPStringBuilder val = new CPStringBuilder(point - start - 1); 457: if (dot != -1) 458: { 459: // If there was a decimal we must combine the two parts that 460: // contain only digits and we must set the scale properly. 461: val.append(in, start, dot - start); 462: val.append(in, dot + 1, point - dot - 1); 463: scale = point - 1 - dot; 464: } 465: else 466: { 467: // If there was no decimal then the unscaled value is just the number 468: // formed from all the digits and the scale is zero. 469: val.append(in, start, point - start); 470: scale = 0; 471: } 472: if (val.length() == 0) 473: throw new NumberFormatException("no digits seen"); 474: 475: // Prepend a negative sign if necessary. 476: if (negative) 477: val.insert(0, '-'); 478: intVal = new BigInteger(val.toString()); 479: 480: // Now parse exponent. 481: // If point < end that means we broke out of the previous loop when we 482: // saw an 'e' or an 'E'. 483: if (point < end) 484: { 485: point++; 486: // Ignore a '+' sign. 487: if (in[point] == '+') 488: point++; 489: 490: // Throw an exception if there were no digits found after the 'e' 491: // or 'E'. 492: if (point >= end) 493: throw new NumberFormatException("no exponent following e or E"); 494: 495: try 496: { 497: // Adjust the scale according to the exponent. 498: // Remember that the value of a BigDecimal is 499: // unscaledValue x Math.pow(10, -scale) 500: scale -= Integer.parseInt(new String(in, point, end - point)); 501: } 502: catch (NumberFormatException ex) 503: { 504: throw new NumberFormatException("malformed exponent"); 505: } 506: } 507: } 508: 509: public BigDecimal (String num) throws NumberFormatException 510: { 511: int len = num.length(); 512: int start = 0, point = 0; 513: int dot = -1; 514: boolean negative = false; 515: if (num.charAt(0) == '+') 516: { 517: ++start; 518: ++point; 519: } 520: else if (num.charAt(0) == '-') 521: { 522: ++start; 523: ++point; 524: negative = true; 525: } 526: 527: while (point < len) 528: { 529: char c = num.charAt (point); 530: if (c == '.') 531: { 532: if (dot >= 0) 533: throw new NumberFormatException ("multiple `.'s in number"); 534: dot = point; 535: } 536: else if (c == 'e' || c == 'E') 537: break; 538: else if (Character.digit (c, 10) < 0) 539: throw new NumberFormatException ("unrecognized character: " + c); 540: ++point; 541: } 542: 543: String val; 544: if (dot >= 0) 545: { 546: val = num.substring (start, dot) + num.substring (dot + 1, point); 547: scale = point - 1 - dot; 548: } 549: else 550: { 551: val = num.substring (start, point); 552: scale = 0; 553: } 554: if (val.length () == 0) 555: throw new NumberFormatException ("no digits seen"); 556: 557: if (negative) 558: val = "-" + val; 559: intVal = new BigInteger (val); 560: 561: // Now parse exponent. 562: if (point < len) 563: { 564: point++; 565: if (num.charAt(point) == '+') 566: point++; 567: 568: if (point >= len ) 569: throw new NumberFormatException ("no exponent following e or E"); 570: 571: try 572: { 573: scale -= Integer.parseInt (num.substring (point)); 574: } 575: catch (NumberFormatException ex) 576: { 577: throw new NumberFormatException ("malformed exponent"); 578: } 579: } 580: } 581: 582: public static BigDecimal valueOf (long val) 583: { 584: return valueOf (val, 0); 585: } 586: 587: public static BigDecimal valueOf (long val, int scale) 588: throws NumberFormatException 589: { 590: if ((scale == 0) && ((int)val == val)) 591: switch ((int) val) 592: { 593: case 0: 594: return ZERO; 595: case 1: 596: return ONE; 597: } 598: 599: return new BigDecimal (BigInteger.valueOf (val), scale); 600: } 601: 602: public BigDecimal add (BigDecimal val) 603: { 604: // For addition, need to line up decimals. Note that the movePointRight 605: // method cannot be used for this as it might return a BigDecimal with 606: // scale == 0 instead of the scale we need. 607: BigInteger op1 = intVal; 608: BigInteger op2 = val.intVal; 609: if (scale < val.scale) 610: op1 = op1.multiply (BigInteger.TEN.pow (val.scale - scale)); 611: else if (scale > val.scale) 612: op2 = op2.multiply (BigInteger.TEN.pow (scale - val.scale)); 613: 614: return new BigDecimal (op1.add (op2), Math.max (scale, val.scale)); 615: } 616: 617: /** 618: * Returns a BigDecimal whose value is found first by calling the 619: * method add(val) and then by rounding according to the MathContext mc. 620: * @param val the augend 621: * @param mc the MathContext for rounding 622: * @throws ArithmeticException if the value is inexact but the rounding is 623: * RoundingMode.UNNECESSARY 624: * @return <code>this</code> + <code>val</code>, rounded if need be 625: * @since 1.5 626: */ 627: public BigDecimal add (BigDecimal val, MathContext mc) 628: { 629: return add(val).round(mc); 630: } 631: 632: public BigDecimal subtract (BigDecimal val) 633: { 634: return this.add(val.negate()); 635: } 636: 637: /** 638: * Returns a BigDecimal whose value is found first by calling the 639: * method subtract(val) and then by rounding according to the MathContext mc. 640: * @param val the subtrahend 641: * @param mc the MathContext for rounding 642: * @throws ArithmeticException if the value is inexact but the rounding is 643: * RoundingMode.UNNECESSARY 644: * @return <code>this</code> - <code>val</code>, rounded if need be 645: * @since 1.5 646: */ 647: public BigDecimal subtract (BigDecimal val, MathContext mc) 648: { 649: return subtract(val).round(mc); 650: } 651: 652: public BigDecimal multiply (BigDecimal val) 653: { 654: return new BigDecimal (intVal.multiply (val.intVal), scale + val.scale); 655: } 656: 657: /** 658: * Returns a BigDecimal whose value is (this x val) before it is rounded 659: * according to the MathContext mc. 660: * @param val the multiplicand 661: * @param mc the MathContext for rounding 662: * @return a new BigDecimal with value approximately (this x val) 663: * @throws ArithmeticException if the value is inexact but the rounding mode 664: * is RoundingMode.UNNECESSARY 665: * @since 1.5 666: */ 667: public BigDecimal multiply (BigDecimal val, MathContext mc) 668: { 669: return multiply(val).round(mc); 670: } 671: 672: public BigDecimal divide (BigDecimal val, int roundingMode) 673: throws ArithmeticException, IllegalArgumentException 674: { 675: return divide (val, scale, roundingMode); 676: } 677: 678: /** 679: * Returns a BigDecimal whose value is (this / val), with the specified scale 680: * and rounding according to the RoundingMode 681: * @param val the divisor 682: * @param scale the scale of the BigDecimal returned 683: * @param roundingMode the rounding mode to use 684: * @return a BigDecimal whose value is approximately (this / val) 685: * @throws ArithmeticException if divisor is zero or the rounding mode is 686: * UNNECESSARY but the specified scale cannot represent the value exactly 687: * @since 1.5 688: */ 689: public BigDecimal divide(BigDecimal val, 690: int scale, RoundingMode roundingMode) 691: { 692: return divide (val, scale, roundingMode.ordinal()); 693: } 694: 695: /** 696: * Returns a BigDecimal whose value is (this / val) rounded according to the 697: * RoundingMode 698: * @param val the divisor 699: * @param roundingMode the rounding mode to use 700: * @return a BigDecimal whose value is approximately (this / val) 701: * @throws ArithmeticException if divisor is zero or the rounding mode is 702: * UNNECESSARY but the specified scale cannot represent the value exactly 703: */ 704: public BigDecimal divide (BigDecimal val, RoundingMode roundingMode) 705: { 706: return divide (val, scale, roundingMode.ordinal()); 707: } 708: 709: public BigDecimal divide(BigDecimal val, int newScale, int roundingMode) 710: throws ArithmeticException, IllegalArgumentException 711: { 712: if (roundingMode < 0 || roundingMode > 7) 713: throw 714: new IllegalArgumentException("illegal rounding mode: " + roundingMode); 715: 716: if (intVal.signum () == 0) // handle special case of 0.0/0.0 717: return newScale == 0 ? ZERO : new BigDecimal (ZERO.intVal, newScale); 718: 719: // Ensure that pow gets a non-negative value. 720: BigInteger valIntVal = val.intVal; 721: int power = newScale - (scale - val.scale); 722: if (power < 0) 723: { 724: // Effectively increase the scale of val to avoid an 725: // ArithmeticException for a negative power. 726: valIntVal = valIntVal.multiply (BigInteger.TEN.pow (-power)); 727: power = 0; 728: } 729: 730: BigInteger dividend = intVal.multiply (BigInteger.TEN.pow (power)); 731: 732: BigInteger parts[] = dividend.divideAndRemainder (valIntVal); 733: 734: BigInteger unrounded = parts[0]; 735: if (parts[1].signum () == 0) // no remainder, no rounding necessary 736: return new BigDecimal (unrounded, newScale); 737: 738: if (roundingMode == ROUND_UNNECESSARY) 739: throw new ArithmeticException ("Rounding necessary"); 740: 741: int sign = intVal.signum () * valIntVal.signum (); 742: 743: if (roundingMode == ROUND_CEILING) 744: roundingMode = (sign > 0) ? ROUND_UP : ROUND_DOWN; 745: else if (roundingMode == ROUND_FLOOR) 746: roundingMode = (sign < 0) ? ROUND_UP : ROUND_DOWN; 747: else 748: { 749: // half is -1 if remainder*2 < positive intValue (*power), 0 if equal, 750: // 1 if >. This implies that the remainder to round is less than, 751: // equal to, or greater than half way to the next digit. 752: BigInteger posRemainder 753: = parts[1].signum () < 0 ? parts[1].negate() : parts[1]; 754: valIntVal = valIntVal.signum () < 0 ? valIntVal.negate () : valIntVal; 755: int half = posRemainder.shiftLeft(1).compareTo(valIntVal); 756: 757: switch(roundingMode) 758: { 759: case ROUND_HALF_UP: 760: roundingMode = (half < 0) ? ROUND_DOWN : ROUND_UP; 761: break; 762: case ROUND_HALF_DOWN: 763: roundingMode = (half > 0) ? ROUND_UP : ROUND_DOWN; 764: break; 765: case ROUND_HALF_EVEN: 766: if (half < 0) 767: roundingMode = ROUND_DOWN; 768: else if (half > 0) 769: roundingMode = ROUND_UP; 770: else if (unrounded.testBit(0)) // odd, then ROUND_HALF_UP 771: roundingMode = ROUND_UP; 772: else // even, ROUND_HALF_DOWN 773: roundingMode = ROUND_DOWN; 774: break; 775: } 776: } 777: 778: if (roundingMode == ROUND_UP) 779: unrounded = unrounded.add (BigInteger.valueOf (sign > 0 ? 1 : -1)); 780: 781: // roundingMode == ROUND_DOWN 782: return new BigDecimal (unrounded, newScale); 783: } 784: 785: /** 786: * Performs division, if the resulting quotient requires rounding 787: * (has a nonterminating decimal expansion), 788: * an ArithmeticException is thrown. 789: * #see divide(BigDecimal, int, int) 790: * @since 1.5 791: */ 792: public BigDecimal divide(BigDecimal divisor) 793: throws ArithmeticException, IllegalArgumentException 794: { 795: return divide(divisor, scale, ROUND_UNNECESSARY); 796: } 797: 798: /** 799: * Returns a BigDecimal whose value is the remainder in the quotient 800: * this / val. This is obtained by 801: * subtract(divideToIntegralValue(val).multiply(val)). 802: * @param val the divisor 803: * @return a BigDecimal whose value is the remainder 804: * @throws ArithmeticException if val == 0 805: * @since 1.5 806: */ 807: public BigDecimal remainder(BigDecimal val) 808: { 809: return subtract(divideToIntegralValue(val).multiply(val)); 810: } 811: 812: /** 813: * Returns a BigDecimal array, the first element of which is the integer part 814: * of this / val, and the second element of which is the remainder of 815: * that quotient. 816: * @param val the divisor 817: * @return the above described BigDecimal array 818: * @throws ArithmeticException if val == 0 819: * @since 1.5 820: */ 821: public BigDecimal[] divideAndRemainder(BigDecimal val) 822: { 823: BigDecimal[] result = new BigDecimal[2]; 824: result[0] = divideToIntegralValue(val); 825: result[1] = subtract(result[0].multiply(val)); 826: return result; 827: } 828: 829: /** 830: * Returns a BigDecimal whose value is the integer part of the quotient 831: * this / val. The preferred scale is this.scale - val.scale. 832: * @param val the divisor 833: * @return a BigDecimal whose value is the integer part of this / val. 834: * @throws ArithmeticException if val == 0 835: * @since 1.5 836: */ 837: public BigDecimal divideToIntegralValue(BigDecimal val) 838: { 839: return divide(val, ROUND_DOWN).floor().setScale(scale - val.scale, ROUND_DOWN); 840: } 841: 842: /** 843: * Mutates this BigDecimal into one with no fractional part, whose value is 844: * equal to the largest integer that is <= to this BigDecimal. Note that 845: * since this method is private it is okay to mutate this BigDecimal. 846: * @return the BigDecimal obtained through the floor operation on this 847: * BigDecimal. 848: */ 849: private BigDecimal floor() 850: { 851: if (scale <= 0) 852: return this; 853: String intValStr = intVal.toString(); 854: intValStr = intValStr.substring(0, intValStr.length() - scale); 855: intVal = new BigInteger(intValStr).multiply(BigInteger.TEN.pow(scale)); 856: return this; 857: } 858: 859: public int compareTo (BigDecimal val) 860: { 861: if (scale == val.scale) 862: return intVal.compareTo (val.intVal); 863: 864: BigInteger thisParts[] = 865: intVal.divideAndRemainder (BigInteger.TEN.pow (scale)); 866: BigInteger valParts[] = 867: val.intVal.divideAndRemainder (BigInteger.TEN.pow (val.scale)); 868: 869: int compare; 870: if ((compare = thisParts[0].compareTo (valParts[0])) != 0) 871: return compare; 872: 873: // quotients are the same, so compare remainders 874: 875: // Add some trailing zeros to the remainder with the smallest scale 876: if (scale < val.scale) 877: thisParts[1] = thisParts[1].multiply 878: (BigInteger.valueOf (10).pow (val.scale - scale)); 879: else if (scale > val.scale) 880: valParts[1] = valParts[1].multiply 881: (BigInteger.valueOf (10).pow (scale - val.scale)); 882: 883: // and compare them 884: return thisParts[1].compareTo (valParts[1]); 885: } 886: 887: public boolean equals (Object o) 888: { 889: return (o instanceof BigDecimal 890: && scale == ((BigDecimal) o).scale 891: && compareTo ((BigDecimal) o) == 0); 892: } 893: 894: public int hashCode() 895: { 896: return intValue() ^ scale; 897: } 898: 899: public BigDecimal max (BigDecimal val) 900: { 901: switch (compareTo (val)) 902: { 903: case 1: 904: return this; 905: default: 906: return val; 907: } 908: } 909: 910: public BigDecimal min (BigDecimal val) 911: { 912: switch (compareTo (val)) 913: { 914: case -1: 915: return this; 916: default: 917: return val; 918: } 919: } 920: 921: public BigDecimal movePointLeft (int n) 922: { 923: return (n < 0) ? movePointRight (-n) : new BigDecimal (intVal, scale + n); 924: } 925: 926: public BigDecimal movePointRight (int n) 927: { 928: if (n < 0) 929: return movePointLeft (-n); 930: 931: if (scale >= n) 932: return new BigDecimal (intVal, scale - n); 933: 934: return new BigDecimal (intVal.multiply 935: (BigInteger.TEN.pow (n - scale)), 0); 936: } 937: 938: public int signum () 939: { 940: return intVal.signum (); 941: } 942: 943: public int scale () 944: { 945: return scale; 946: } 947: 948: public BigInteger unscaledValue() 949: { 950: return intVal; 951: } 952: 953: public BigDecimal abs () 954: { 955: return new BigDecimal (intVal.abs (), scale); 956: } 957: 958: public BigDecimal negate () 959: { 960: return new BigDecimal (intVal.negate (), scale); 961: } 962: 963: /** 964: * Returns a BigDecimal whose value is found first by negating this via 965: * the negate() method, then by rounding according to the MathContext mc. 966: * @param mc the MathContext for rounding 967: * @return a BigDecimal whose value is approximately (-this) 968: * @throws ArithmeticException if the value is inexact but the rounding mode 969: * is RoundingMode.UNNECESSARY 970: * @since 1.5 971: */ 972: public BigDecimal negate(MathContext mc) 973: { 974: BigDecimal result = negate(); 975: if (mc.getPrecision() != 0) 976: result = result.round(mc); 977: return result; 978: } 979: 980: /** 981: * Returns this BigDecimal. This is included for symmetry with the 982: * method negate(). 983: * @return this 984: * @since 1.5 985: */ 986: public BigDecimal plus() 987: { 988: return this; 989: } 990: 991: /** 992: * Returns a BigDecimal whose value is found by rounding <code>this</code> 993: * according to the MathContext. This is the same as round(MathContext). 994: * @param mc the MathContext for rounding 995: * @return a BigDecimal whose value is <code>this</code> before being rounded 996: * @throws ArithmeticException if the value is inexact but the rounding mode 997: * is RoundingMode.UNNECESSARY 998: * @since 1.5 999: */ 1000: public BigDecimal plus(MathContext mc) 1001: { 1002: return round(mc); 1003: } 1004: 1005: /** 1006: * Returns a BigDecimal which is this BigDecimal rounded according to the 1007: * MathContext rounding settings. 1008: * @param mc the MathContext that tells us how to round 1009: * @return the rounded BigDecimal 1010: */ 1011: public BigDecimal round(MathContext mc) 1012: { 1013: int mcPrecision = mc.getPrecision(); 1014: int numToChop = precision() - mcPrecision; 1015: // If mc specifies not to chop any digits or if we've already chopped 1016: // enough digits (say by using a MathContext in the constructor for this 1017: // BigDecimal) then just return this. 1018: if (mcPrecision == 0 || numToChop <= 0) 1019: return this; 1020: 1021: // Make a new BigDecimal which is the correct power of 10 to chop off 1022: // the required number of digits and then call divide. 1023: BigDecimal div = new BigDecimal(BigInteger.TEN.pow(numToChop)); 1024: BigDecimal rounded = divide(div, scale, mc.getRoundingMode().ordinal()); 1025: rounded.scale -= numToChop; 1026: rounded.precision = mcPrecision; 1027: return rounded; 1028: } 1029: 1030: /** 1031: * Returns the precision of this BigDecimal (the number of digits in the 1032: * unscaled value). The precision of a zero value is 1. 1033: * @return the number of digits in the unscaled value, or 1 if the value 1034: * is zero. 1035: */ 1036: public int precision() 1037: { 1038: if (precision == 0) 1039: { 1040: String s = intVal.toString(); 1041: precision = s.length() - (( s.charAt(0) == '-' ) ? 1 : 0); 1042: } 1043: return precision; 1044: } 1045: 1046: /** 1047: * Returns the String representation of this BigDecimal, using scientific 1048: * notation if necessary. The following steps are taken to generate 1049: * the result: 1050: * 1051: * 1. the BigInteger unscaledValue's toString method is called and if 1052: * <code>scale == 0<code> is returned. 1053: * 2. an <code>int adjExp</code> is created which is equal to the negation 1054: * of <code>scale</code> plus the number of digits in the unscaled value, 1055: * minus one. 1056: * 3. if <code>scale >= 0 && adjExp >= -6</code> then we represent this 1057: * BigDecimal without scientific notation. A decimal is added if the 1058: * scale is positive and zeros are prepended as necessary. 1059: * 4. if scale is negative or adjExp is less than -6 we use scientific 1060: * notation. If the unscaled value has more than one digit, a decimal 1061: * as inserted after the first digit, the character 'E' is appended 1062: * and adjExp is appended. 1063: */ 1064: public String toString() 1065: { 1066: // bigStr is the String representation of the unscaled value. If 1067: // scale is zero we simply return this. 1068: String bigStr = intVal.toString(); 1069: if (scale == 0) 1070: return bigStr; 1071: 1072: boolean negative = (bigStr.charAt(0) == '-'); 1073: int point = bigStr.length() - scale - (negative ? 1 : 0); 1074: 1075: CPStringBuilder val = new CPStringBuilder(); 1076: 1077: if (scale >= 0 && (point - 1) >= -6) 1078: { 1079: // Convert to character form without scientific notation. 1080: if (point <= 0) 1081: { 1082: // Zeros need to be prepended to the StringBuilder. 1083: if (negative) 1084: val.append('-'); 1085: // Prepend a '0' and a '.' and then as many more '0's as necessary. 1086: val.append('0').append('.'); 1087: while (point < 0) 1088: { 1089: val.append('0'); 1090: point++; 1091: } 1092: // Append the unscaled value. 1093: val.append(bigStr.substring(negative ? 1 : 0)); 1094: } 1095: else 1096: { 1097: // No zeros need to be prepended so the String is simply the 1098: // unscaled value with the decimal point inserted. 1099: val.append(bigStr); 1100: val.insert(point + (negative ? 1 : 0), '.'); 1101: } 1102: } 1103: else 1104: { 1105: // We must use scientific notation to represent this BigDecimal. 1106: val.append(bigStr); 1107: // If there is more than one digit in the unscaled value we put a 1108: // decimal after the first digit. 1109: if (bigStr.length() > 1) 1110: val.insert( ( negative ? 2 : 1 ), '.'); 1111: // And then append 'E' and the exponent = (point - 1). 1112: val.append('E'); 1113: if (point - 1 >= 0) 1114: val.append('+'); 1115: val.append( point - 1 ); 1116: } 1117: return val.toString(); 1118: } 1119: 1120: /** 1121: * Returns the String representation of this BigDecimal, using engineering 1122: * notation if necessary. This is similar to toString() but when exponents 1123: * are used the exponent is made to be a multiple of 3 such that the integer 1124: * part is between 1 and 999. 1125: * 1126: * @return a String representation of this BigDecimal in engineering notation 1127: * @since 1.5 1128: */ 1129: public String toEngineeringString() 1130: { 1131: // bigStr is the String representation of the unscaled value. If 1132: // scale is zero we simply return this. 1133: String bigStr = intVal.toString(); 1134: if (scale == 0) 1135: return bigStr; 1136: 1137: boolean negative = (bigStr.charAt(0) == '-'); 1138: int point = bigStr.length() - scale - (negative ? 1 : 0); 1139: 1140: // This is the adjusted exponent described above. 1141: int adjExp = point - 1; 1142: CPStringBuilder val = new CPStringBuilder(); 1143: 1144: if (scale >= 0 && adjExp >= -6) 1145: { 1146: // Convert to character form without scientific notation. 1147: if (point <= 0) 1148: { 1149: // Zeros need to be prepended to the StringBuilder. 1150: if (negative) 1151: val.append('-'); 1152: // Prepend a '0' and a '.' and then as many more '0's as necessary. 1153: val.append('0').append('.'); 1154: while (point < 0) 1155: { 1156: val.append('0'); 1157: point++; 1158: } 1159: // Append the unscaled value. 1160: val.append(bigStr.substring(negative ? 1 : 0)); 1161: } 1162: else 1163: { 1164: // No zeros need to be prepended so the String is simply the 1165: // unscaled value with the decimal point inserted. 1166: val.append(bigStr); 1167: val.insert(point + (negative ? 1 : 0), '.'); 1168: } 1169: } 1170: else 1171: { 1172: // We must use scientific notation to represent this BigDecimal. 1173: // The exponent must be a multiple of 3 and the integer part 1174: // must be between 1 and 999. 1175: val.append(bigStr); 1176: int zeros = adjExp % 3; 1177: int dot = 1; 1178: if (adjExp > 0) 1179: { 1180: // If the exponent is positive we just move the decimal to the 1181: // right and decrease the exponent until it is a multiple of 3. 1182: dot += zeros; 1183: adjExp -= zeros; 1184: } 1185: else 1186: { 1187: // If the exponent is negative then we move the dot to the right 1188: // and decrease the exponent (increase its magnitude) until 1189: // it is a multiple of 3. Note that this is not adjExp -= zeros 1190: // because the mod operator doesn't give us the distance to the 1191: // correct multiple of 3. (-5 mod 3) is -2 but the distance from 1192: // -5 to the correct multiple of 3 (-6) is 1, not 2. 1193: if (zeros == -2) 1194: { 1195: dot += 1; 1196: adjExp -= 1; 1197: } 1198: else if (zeros == -1) 1199: { 1200: dot += 2; 1201: adjExp -= 2; 1202: } 1203: } 1204: 1205: // Either we have to append zeros because, for example, 1.1E+5 should 1206: // be 110E+3, or we just have to put the decimal in the right place. 1207: if (dot > val.length()) 1208: { 1209: while (dot > val.length()) 1210: val.append('0'); 1211: } 1212: else if (bigStr.length() > dot) 1213: val.insert(dot + (negative ? 1 : 0), '.'); 1214: 1215: // And then append 'E' and the exponent (adjExp). 1216: val.append('E'); 1217: if (adjExp >= 0) 1218: val.append('+'); 1219: val.append(adjExp); 1220: } 1221: return val.toString(); 1222: } 1223: 1224: /** 1225: * Returns a String representation of this BigDecimal without using 1226: * scientific notation. This is how toString() worked for releases 1.4 1227: * and previous. Zeros may be added to the end of the String. For 1228: * example, an unscaled value of 1234 and a scale of -3 would result in 1229: * the String 1234000, but the toString() method would return 1230: * 1.234E+6. 1231: * @return a String representation of this BigDecimal 1232: * @since 1.5 1233: */ 1234: public String toPlainString() 1235: { 1236: // If the scale is zero we simply return the String representation of the 1237: // unscaled value. 1238: String bigStr = intVal.toString(); 1239: if (scale == 0) 1240: return bigStr; 1241: 1242: // Remember if we have to put a negative sign at the start. 1243: boolean negative = (bigStr.charAt(0) == '-'); 1244: 1245: int point = bigStr.length() - scale - (negative ? 1 : 0); 1246: 1247: CPStringBuilder sb = new CPStringBuilder(bigStr.length() + 2 1248: + (point <= 0 ? (-point + 1) : 0)); 1249: if (point <= 0) 1250: { 1251: // We have to prepend zeros and a decimal point. 1252: if (negative) 1253: sb.append('-'); 1254: sb.append('0').append('.'); 1255: while (point < 0) 1256: { 1257: sb.append('0'); 1258: point++; 1259: } 1260: sb.append(bigStr.substring(negative ? 1 : 0)); 1261: } 1262: else if (point < bigStr.length()) 1263: { 1264: // No zeros need to be prepended or appended, just put the decimal 1265: // in the right place. 1266: sb.append(bigStr); 1267: sb.insert(point + (negative ? 1 : 0), '.'); 1268: } 1269: else 1270: { 1271: // We must append zeros instead of using scientific notation. 1272: sb.append(bigStr); 1273: for (int i = bigStr.length(); i < point; i++) 1274: sb.append('0'); 1275: } 1276: return sb.toString(); 1277: } 1278: 1279: /** 1280: * Converts this BigDecimal to a BigInteger. Any fractional part will 1281: * be discarded. 1282: * @return a BigDecimal whose value is equal to floor[this] 1283: */ 1284: public BigInteger toBigInteger () 1285: { 1286: // If scale > 0 then we must divide, if scale > 0 then we must multiply, 1287: // and if scale is zero then we just return intVal; 1288: if (scale > 0) 1289: return intVal.divide (BigInteger.TEN.pow (scale)); 1290: else if (scale < 0) 1291: return intVal.multiply(BigInteger.TEN.pow(-scale)); 1292: return intVal; 1293: } 1294: 1295: /** 1296: * Converts this BigDecimal into a BigInteger, throwing an 1297: * ArithmeticException if the conversion is not exact. 1298: * @return a BigInteger whose value is equal to the value of this BigDecimal 1299: * @since 1.5 1300: */ 1301: public BigInteger toBigIntegerExact() 1302: { 1303: if (scale > 0) 1304: { 1305: // If we have to divide, we must check if the result is exact. 1306: BigInteger[] result = 1307: intVal.divideAndRemainder(BigInteger.TEN.pow(scale)); 1308: if (result[1].equals(BigInteger.ZERO)) 1309: return result[0]; 1310: throw new ArithmeticException("No exact BigInteger representation"); 1311: } 1312: else if (scale < 0) 1313: // If we're multiplying instead, then we needn't check for exactness. 1314: return intVal.multiply(BigInteger.TEN.pow(-scale)); 1315: // If the scale is zero we can simply return intVal. 1316: return intVal; 1317: } 1318: 1319: public int intValue () 1320: { 1321: return toBigInteger ().intValue (); 1322: } 1323: 1324: /** 1325: * Returns a BigDecimal which is numerically equal to this BigDecimal but 1326: * with no trailing zeros in the representation. For example, if this 1327: * BigDecimal has [unscaledValue, scale] = [6313000, 4] this method returns 1328: * a BigDecimal with [unscaledValue, scale] = [6313, 1]. As another 1329: * example, [12400, -2] would become [124, -4]. 1330: * @return a numerically equal BigDecimal with no trailing zeros 1331: */ 1332: public BigDecimal stripTrailingZeros() 1333: { 1334: String intValStr = intVal.toString(); 1335: int newScale = scale; 1336: int pointer = intValStr.length() - 1; 1337: // This loop adjusts pointer which will be used to give us the substring 1338: // of intValStr to use in our new BigDecimal, and also accordingly 1339: // adjusts the scale of our new BigDecimal. 1340: while (intValStr.charAt(pointer) == '0') 1341: { 1342: pointer --; 1343: newScale --; 1344: } 1345: // Create a new BigDecimal with the appropriate substring and then 1346: // set its scale. 1347: BigDecimal result = new BigDecimal(intValStr.substring(0, pointer + 1)); 1348: result.scale = newScale; 1349: return result; 1350: } 1351: 1352: public long longValue () 1353: { 1354: return toBigInteger().longValue(); 1355: } 1356: 1357: public float floatValue() 1358: { 1359: return Float.valueOf(toString()).floatValue(); 1360: } 1361: 1362: public double doubleValue() 1363: { 1364: return Double.valueOf(toString()).doubleValue(); 1365: } 1366: 1367: public BigDecimal setScale (int scale) throws ArithmeticException 1368: { 1369: return setScale (scale, ROUND_UNNECESSARY); 1370: } 1371: 1372: public BigDecimal setScale (int scale, int roundingMode) 1373: throws ArithmeticException, IllegalArgumentException 1374: { 1375: // NOTE: The 1.5 JRE doesn't throw this, ones prior to it do and 1376: // the spec says it should. Nevertheless, if 1.6 doesn't fix this 1377: // we should consider removing it. 1378: if( scale < 0 ) throw new ArithmeticException("Scale parameter < 0."); 1379: return divide (ONE, scale, roundingMode); 1380: } 1381: 1382: /** 1383: * Returns a BigDecimal whose value is the same as this BigDecimal but whose 1384: * representation has a scale of <code>newScale</code>. If the scale is 1385: * reduced then rounding may occur, according to the RoundingMode. 1386: * @param newScale 1387: * @param roundingMode 1388: * @return a BigDecimal whose scale is as given, whose value is 1389: * <code>this</code> with possible rounding 1390: * @throws ArithmeticException if the rounding mode is UNNECESSARY but 1391: * rounding is required 1392: * @since 1.5 1393: */ 1394: public BigDecimal setScale(int newScale, RoundingMode roundingMode) 1395: { 1396: return setScale(newScale, roundingMode.ordinal()); 1397: } 1398: 1399: /** 1400: * Returns a new BigDecimal constructed from the BigDecimal(String) 1401: * constructor using the Double.toString(double) method to obtain 1402: * the String. 1403: * @param val the double value used in Double.toString(double) 1404: * @return a BigDecimal representation of val 1405: * @throws NumberFormatException if val is NaN or infinite 1406: * @since 1.5 1407: */ 1408: public static BigDecimal valueOf(double val) 1409: { 1410: if (Double.isInfinite(val) || Double.isNaN(val)) 1411: throw new NumberFormatException("argument cannot be NaN or infinite."); 1412: return new BigDecimal(Double.toString(val)); 1413: } 1414: 1415: /** 1416: * Returns a BigDecimal whose numerical value is the numerical value 1417: * of this BigDecimal multiplied by 10 to the power of <code>n</code>. 1418: * @param n the power of ten 1419: * @return the new BigDecimal 1420: * @since 1.5 1421: */ 1422: public BigDecimal scaleByPowerOfTen(int n) 1423: { 1424: BigDecimal result = new BigDecimal(intVal, scale - n); 1425: result.precision = precision; 1426: return result; 1427: } 1428: 1429: /** 1430: * Returns a BigDecimal whose value is <code>this</code> to the power of 1431: * <code>n</code>. 1432: * @param n the power 1433: * @return the new BigDecimal 1434: * @since 1.5 1435: */ 1436: public BigDecimal pow(int n) 1437: { 1438: if (n < 0 || n > 999999999) 1439: throw new ArithmeticException("n must be between 0 and 999999999"); 1440: BigDecimal result = new BigDecimal(intVal.pow(n), scale * n); 1441: return result; 1442: } 1443: 1444: /** 1445: * Returns a BigDecimal whose value is determined by first calling pow(n) 1446: * and then by rounding according to the MathContext mc. 1447: * @param n the power 1448: * @param mc the MathContext 1449: * @return the new BigDecimal 1450: * @throws ArithmeticException if n < 0 or n > 999999999 or if the result is 1451: * inexact but the rounding is RoundingMode.UNNECESSARY 1452: * @since 1.5 1453: */ 1454: public BigDecimal pow(int n, MathContext mc) 1455: { 1456: // FIXME: The specs claim to use the X3.274-1996 algorithm. We 1457: // currently do not. 1458: return pow(n).round(mc); 1459: } 1460: 1461: /** 1462: * Returns a BigDecimal whose value is the absolute value of this BigDecimal 1463: * with rounding according to the given MathContext. 1464: * @param mc the MathContext 1465: * @return the new BigDecimal 1466: */ 1467: public BigDecimal abs(MathContext mc) 1468: { 1469: BigDecimal result = abs(); 1470: result = result.round(mc); 1471: return result; 1472: } 1473: 1474: /** 1475: * Returns the size of a unit in the last place of this BigDecimal. This 1476: * returns a BigDecimal with [unscaledValue, scale] = [1, this.scale()]. 1477: * @return the size of a unit in the last place of <code>this</code>. 1478: * @since 1.5 1479: */ 1480: public BigDecimal ulp() 1481: { 1482: return new BigDecimal(BigInteger.ONE, scale); 1483: } 1484: 1485: /** 1486: * Converts this BigDecimal to a long value. 1487: * @return the long value 1488: * @throws ArithmeticException if rounding occurs or if overflow occurs 1489: * @since 1.5 1490: */ 1491: public long longValueExact() 1492: { 1493: // Set scale will throw an exception if rounding occurs. 1494: BigDecimal temp = setScale(0, ROUND_UNNECESSARY); 1495: BigInteger tempVal = temp.intVal; 1496: // Check for overflow. 1497: long result = intVal.longValue(); 1498: if (tempVal.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 1 1499: || (result < 0 && signum() == 1) || (result > 0 && signum() == -1)) 1500: throw new ArithmeticException("this BigDecimal is too " + 1501: "large to fit into the return type"); 1502: 1503: return intVal.longValue(); 1504: } 1505: 1506: /** 1507: * Converts this BigDecimal into an int by first calling longValueExact 1508: * and then checking that the <code>long</code> returned from that 1509: * method fits into an <code>int</code>. 1510: * @return an int whose value is <code>this</code> 1511: * @throws ArithmeticException if this BigDecimal has a fractional part 1512: * or is too large to fit into an int. 1513: * @since 1.5 1514: */ 1515: public int intValueExact() 1516: { 1517: long temp = longValueExact(); 1518: int result = (int)temp; 1519: if (result != temp) 1520: throw new ArithmeticException ("this BigDecimal cannot fit into an int"); 1521: return result; 1522: } 1523: 1524: /** 1525: * Converts this BigDecimal into a byte by first calling longValueExact 1526: * and then checking that the <code>long</code> returned from that 1527: * method fits into a <code>byte</code>. 1528: * @return a byte whose value is <code>this</code> 1529: * @throws ArithmeticException if this BigDecimal has a fractional part 1530: * or is too large to fit into a byte. 1531: * @since 1.5 1532: */ 1533: public byte byteValueExact() 1534: { 1535: long temp = longValueExact(); 1536: byte result = (byte)temp; 1537: if (result != temp) 1538: throw new ArithmeticException ("this BigDecimal cannot fit into a byte"); 1539: return result; 1540: } 1541: 1542: /** 1543: * Converts this BigDecimal into a short by first calling longValueExact 1544: * and then checking that the <code>long</code> returned from that 1545: * method fits into a <code>short</code>. 1546: * @return a short whose value is <code>this</code> 1547: * @throws ArithmeticException if this BigDecimal has a fractional part 1548: * or is too large to fit into a short. 1549: * @since 1.5 1550: */ 1551: public short shortValueExact() 1552: { 1553: long temp = longValueExact(); 1554: short result = (short)temp; 1555: if (result != temp) 1556: throw new ArithmeticException ("this BigDecimal cannot fit into a short"); 1557: return result; 1558: } 1559: }