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 815: * @return the above described BigDecimal array 816: * @throws ArithmeticException if val == 0 817: * @since 1.5 818: */ 819: public BigDecimal[] divideAndRemainder(BigDecimal val) 820: { 821: BigDecimal[] result = new BigDecimal[2]; 822: result[0] = divideToIntegralValue(val); 823: result[1] = subtract(result[0].multiply(val)); 824: return result; 825: } 826: 827: /** 828: * Returns a BigDecimal whose value is the integer part of the quotient 829: * this / val. The preferred scale is this.scale - val.scale. 830: * @param val the divisor 831: * @return a BigDecimal whose value is the integer part of this / val. 832: * @throws ArithmeticException if val == 0 833: * @since 1.5 834: */ 835: public BigDecimal divideToIntegralValue(BigDecimal val) 836: { 837: return divide(val, ROUND_DOWN).floor().setScale(scale - val.scale, ROUND_DOWN); 838: } 839: 840: /** 841: * Mutates this BigDecimal into one with no fractional part, whose value is 842: * equal to the largest integer that is <= to this BigDecimal. Note that 843: * since this method is private it is okay to mutate this BigDecimal. 844: * @return the BigDecimal obtained through the floor operation on this 845: * BigDecimal. 846: */ 847: private BigDecimal floor() 848: { 849: if (scale <= 0) 850: return this; 851: String intValStr = intVal.toString(); 852: intValStr = intValStr.substring(0, intValStr.length() - scale); 853: intVal = new BigInteger(intValStr).multiply(BigInteger.TEN.pow(scale)); 854: return this; 855: } 856: 857: public int compareTo (BigDecimal val) 858: { 859: if (scale == val.scale) 860: return intVal.compareTo (val.intVal); 861: 862: BigInteger thisParts[] = 863: intVal.divideAndRemainder (BigInteger.TEN.pow (scale)); 864: BigInteger valParts[] = 865: val.intVal.divideAndRemainder (BigInteger.TEN.pow (val.scale)); 866: 867: int compare; 868: if ((compare = thisParts[0].compareTo (valParts[0])) != 0) 869: return compare; 870: 871: // quotients are the same, so compare remainders 872: 873: // Add some trailing zeros to the remainder with the smallest scale 874: if (scale < val.scale) 875: thisParts[1] = thisParts[1].multiply 876: (BigInteger.valueOf (10).pow (val.scale - scale)); 877: else if (scale > val.scale) 878: valParts[1] = valParts[1].multiply 879: (BigInteger.valueOf (10).pow (scale - val.scale)); 880: 881: // and compare them 882: return thisParts[1].compareTo (valParts[1]); 883: } 884: 885: public boolean equals (Object o) 886: { 887: return (o instanceof BigDecimal 888: && scale == ((BigDecimal) o).scale 889: && compareTo ((BigDecimal) o) == 0); 890: } 891: 892: public int hashCode() 893: { 894: return intValue() ^ scale; 895: } 896: 897: public BigDecimal max (BigDecimal val) 898: { 899: switch (compareTo (val)) 900: { 901: case 1: 902: return this; 903: default: 904: return val; 905: } 906: } 907: 908: public BigDecimal min (BigDecimal val) 909: { 910: switch (compareTo (val)) 911: { 912: case -1: 913: return this; 914: default: 915: return val; 916: } 917: } 918: 919: public BigDecimal movePointLeft (int n) 920: { 921: return (n < 0) ? movePointRight (-n) : new BigDecimal (intVal, scale + n); 922: } 923: 924: public BigDecimal movePointRight (int n) 925: { 926: if (n < 0) 927: return movePointLeft (-n); 928: 929: if (scale >= n) 930: return new BigDecimal (intVal, scale - n); 931: 932: return new BigDecimal (intVal.multiply 933: (BigInteger.TEN.pow (n - scale)), 0); 934: } 935: 936: public int signum () 937: { 938: return intVal.signum (); 939: } 940: 941: public int scale () 942: { 943: return scale; 944: } 945: 946: public BigInteger unscaledValue() 947: { 948: return intVal; 949: } 950: 951: public BigDecimal abs () 952: { 953: return new BigDecimal (intVal.abs (), scale); 954: } 955: 956: public BigDecimal negate () 957: { 958: return new BigDecimal (intVal.negate (), scale); 959: } 960: 961: /** 962: * Returns a BigDecimal whose value is found first by negating this via 963: * the negate() method, then by rounding according to the MathContext mc. 964: * @param mc the MathContext for rounding 965: * @return a BigDecimal whose value is approximately (-this) 966: * @throws ArithmeticException if the value is inexact but the rounding mode 967: * is RoundingMode.UNNECESSARY 968: * @since 1.5 969: */ 970: public BigDecimal negate(MathContext mc) 971: { 972: BigDecimal result = negate(); 973: if (mc.getPrecision() != 0) 974: result = result.round(mc); 975: return result; 976: } 977: 978: /** 979: * Returns this BigDecimal. This is included for symmetry with the 980: * method negate(). 981: * @return this 982: * @since 1.5 983: */ 984: public BigDecimal plus() 985: { 986: return this; 987: } 988: 989: /** 990: * Returns a BigDecimal whose value is found by rounding <code>this</code> 991: * according to the MathContext. This is the same as round(MathContext). 992: * @param mc the MathContext for rounding 993: * @return a BigDecimal whose value is <code>this</code> before being rounded 994: * @throws ArithmeticException if the value is inexact but the rounding mode 995: * is RoundingMode.UNNECESSARY 996: * @since 1.5 997: */ 998: public BigDecimal plus(MathContext mc) 999: { 1000: return round(mc); 1001: } 1002: 1003: /** 1004: * Returns a BigDecimal which is this BigDecimal rounded according to the 1005: * MathContext rounding settings. 1006: * @param mc the MathContext that tells us how to round 1007: * @return the rounded BigDecimal 1008: */ 1009: public BigDecimal round(MathContext mc) 1010: { 1011: int mcPrecision = mc.getPrecision(); 1012: int numToChop = precision() - mcPrecision; 1013: // If mc specifies not to chop any digits or if we've already chopped 1014: // enough digits (say by using a MathContext in the constructor for this 1015: // BigDecimal) then just return this. 1016: if (mcPrecision == 0 || numToChop <= 0) 1017: return this; 1018: 1019: // Make a new BigDecimal which is the correct power of 10 to chop off 1020: // the required number of digits and then call divide. 1021: BigDecimal div = new BigDecimal(BigInteger.TEN.pow(numToChop)); 1022: BigDecimal rounded = divide(div, scale, mc.getRoundingMode().ordinal()); 1023: rounded.scale -= numToChop; 1024: rounded.precision = mcPrecision; 1025: return rounded; 1026: } 1027: 1028: /** 1029: * Returns the precision of this BigDecimal (the number of digits in the 1030: * unscaled value). The precision of a zero value is 1. 1031: * @return the number of digits in the unscaled value, or 1 if the value 1032: * is zero. 1033: */ 1034: public int precision() 1035: { 1036: if (precision == 0) 1037: { 1038: String s = intVal.toString(); 1039: precision = s.length() - (( s.charAt(0) == '-' ) ? 1 : 0); 1040: } 1041: return precision; 1042: } 1043: 1044: /** 1045: * Returns the String representation of this BigDecimal, using scientific 1046: * notation if necessary. The following steps are taken to generate 1047: * the result: 1048: * 1049: * 1. the BigInteger unscaledValue's toString method is called and if 1050: * <code>scale == 0<code> is returned. 1051: * 2. an <code>int adjExp</code> is created which is equal to the negation 1052: * of <code>scale</code> plus the number of digits in the unscaled value, 1053: * minus one. 1054: * 3. if <code>scale >= 0 && adjExp >= -6</code> then we represent this 1055: * BigDecimal without scientific notation. A decimal is added if the 1056: * scale is positive and zeros are prepended as necessary. 1057: * 4. if scale is negative or adjExp is less than -6 we use scientific 1058: * notation. If the unscaled value has more than one digit, a decimal 1059: * as inserted after the first digit, the character 'E' is appended 1060: * and adjExp is appended. 1061: */ 1062: public String toString() 1063: { 1064: // bigStr is the String representation of the unscaled value. If 1065: // scale is zero we simply return this. 1066: String bigStr = intVal.toString(); 1067: if (scale == 0) 1068: return bigStr; 1069: 1070: boolean negative = (bigStr.charAt(0) == '-'); 1071: int point = bigStr.length() - scale - (negative ? 1 : 0); 1072: 1073: StringBuilder val = new StringBuilder(); 1074: 1075: if (scale >= 0 && (point - 1) >= -6) 1076: { 1077: // Convert to character form without scientific notation. 1078: if (point <= 0) 1079: { 1080: // Zeros need to be prepended to the StringBuilder. 1081: if (negative) 1082: val.append('-'); 1083: // Prepend a '0' and a '.' and then as many more '0's as necessary. 1084: val.append('0').append('.'); 1085: while (point < 0) 1086: { 1087: val.append('0'); 1088: point++; 1089: } 1090: // Append the unscaled value. 1091: val.append(bigStr.substring(negative ? 1 : 0)); 1092: } 1093: else 1094: { 1095: // No zeros need to be prepended so the String is simply the 1096: // unscaled value with the decimal point inserted. 1097: val.append(bigStr); 1098: val.insert(point + (negative ? 1 : 0), '.'); 1099: } 1100: } 1101: else 1102: { 1103: // We must use scientific notation to represent this BigDecimal. 1104: val.append(bigStr); 1105: // If there is more than one digit in the unscaled value we put a 1106: // decimal after the first digit. 1107: if (bigStr.length() > 1) 1108: val.insert( ( negative ? 2 : 1 ), '.'); 1109: // And then append 'E' and the exponent = (point - 1). 1110: val.append('E'); 1111: if (point - 1 >= 0) 1112: val.append('+'); 1113: val.append( point - 1 ); 1114: } 1115: return val.toString(); 1116: } 1117: 1118: /** 1119: * Returns the String representation of this BigDecimal, using engineering 1120: * notation if necessary. This is similar to toString() but when exponents 1121: * are used the exponent is made to be a multiple of 3 such that the integer 1122: * part is between 1 and 999. 1123: * 1124: * @return a String representation of this BigDecimal in engineering notation 1125: * @since 1.5 1126: */ 1127: public String toEngineeringString() 1128: { 1129: // bigStr is the String representation of the unscaled value. If 1130: // scale is zero we simply return this. 1131: String bigStr = intVal.toString(); 1132: if (scale == 0) 1133: return bigStr; 1134: 1135: boolean negative = (bigStr.charAt(0) == '-'); 1136: int point = bigStr.length() - scale - (negative ? 1 : 0); 1137: 1138: // This is the adjusted exponent described above. 1139: int adjExp = point - 1; 1140: StringBuilder val = new StringBuilder(); 1141: 1142: if (scale >= 0 && adjExp >= -6) 1143: { 1144: // Convert to character form without scientific notation. 1145: if (point <= 0) 1146: { 1147: // Zeros need to be prepended to the StringBuilder. 1148: if (negative) 1149: val.append('-'); 1150: // Prepend a '0' and a '.' and then as many more '0's as necessary. 1151: val.append('0').append('.'); 1152: while (point < 0) 1153: { 1154: val.append('0'); 1155: point++; 1156: } 1157: // Append the unscaled value. 1158: val.append(bigStr.substring(negative ? 1 : 0)); 1159: } 1160: else 1161: { 1162: // No zeros need to be prepended so the String is simply the 1163: // unscaled value with the decimal point inserted. 1164: val.append(bigStr); 1165: val.insert(point + (negative ? 1 : 0), '.'); 1166: } 1167: } 1168: else 1169: { 1170: // We must use scientific notation to represent this BigDecimal. 1171: // The exponent must be a multiple of 3 and the integer part 1172: // must be between 1 and 999. 1173: val.append(bigStr); 1174: int zeros = adjExp % 3; 1175: int dot = 1; 1176: if (adjExp > 0) 1177: { 1178: // If the exponent is positive we just move the decimal to the 1179: // right and decrease the exponent until it is a multiple of 3. 1180: dot += zeros; 1181: adjExp -= zeros; 1182: } 1183: else 1184: { 1185: // If the exponent is negative then we move the dot to the right 1186: // and decrease the exponent (increase its magnitude) until 1187: // it is a multiple of 3. Note that this is not adjExp -= zeros 1188: // because the mod operator doesn't give us the distance to the 1189: // correct multiple of 3. (-5 mod 3) is -2 but the distance from 1190: // -5 to the correct multiple of 3 (-6) is 1, not 2. 1191: if (zeros == -2) 1192: { 1193: dot += 1; 1194: adjExp -= 1; 1195: } 1196: else if (zeros == -1) 1197: { 1198: dot += 2; 1199: adjExp -= 2; 1200: } 1201: } 1202: 1203: // Either we have to append zeros because, for example, 1.1E+5 should 1204: // be 110E+3, or we just have to put the decimal in the right place. 1205: if (dot > val.length()) 1206: { 1207: while (dot > val.length()) 1208: val.append('0'); 1209: } 1210: else if (bigStr.length() > dot) 1211: val.insert(dot + (negative ? 1 : 0), '.'); 1212: 1213: // And then append 'E' and the exponent (adjExp). 1214: val.append('E'); 1215: if (adjExp >= 0) 1216: val.append('+'); 1217: val.append(adjExp); 1218: } 1219: return val.toString(); 1220: } 1221: 1222: /** 1223: * Returns a String representation of this BigDecimal without using 1224: * scientific notation. This is how toString() worked for releases 1.4 1225: * and previous. Zeros may be added to the end of the String. For 1226: * example, an unscaled value of 1234 and a scale of -3 would result in 1227: * the String 1234000, but the toString() method would return 1228: * 1.234E+6. 1229: * @return a String representation of this BigDecimal 1230: * @since 1.5 1231: */ 1232: public String toPlainString() 1233: { 1234: // If the scale is zero we simply return the String representation of the 1235: // unscaled value. 1236: String bigStr = intVal.toString(); 1237: if (scale == 0) 1238: return bigStr; 1239: 1240: // Remember if we have to put a negative sign at the start. 1241: boolean negative = (bigStr.charAt(0) == '-'); 1242: 1243: int point = bigStr.length() - scale - (negative ? 1 : 0); 1244: 1245: StringBuffer sb = new StringBuffer(bigStr.length() + 2 1246: + (point <= 0 ? (-point + 1) : 0)); 1247: if (point <= 0) 1248: { 1249: // We have to prepend zeros and a decimal point. 1250: if (negative) 1251: sb.append('-'); 1252: sb.append('0').append('.'); 1253: while (point < 0) 1254: { 1255: sb.append('0'); 1256: point++; 1257: } 1258: sb.append(bigStr.substring(negative ? 1 : 0)); 1259: } 1260: else if (point < bigStr.length()) 1261: { 1262: // No zeros need to be prepended or appended, just put the decimal 1263: // in the right place. 1264: sb.append(bigStr); 1265: sb.insert(point + (negative ? 1 : 0), '.'); 1266: } 1267: else 1268: { 1269: // We must append zeros instead of using scientific notation. 1270: sb.append(bigStr); 1271: for (int i = bigStr.length(); i < point; i++) 1272: sb.append('0'); 1273: } 1274: return sb.toString(); 1275: } 1276: 1277: /** 1278: * Converts this BigDecimal to a BigInteger. Any fractional part will 1279: * be discarded. 1280: * @return a BigDecimal whose value is equal to floor[this] 1281: */ 1282: public BigInteger toBigInteger () 1283: { 1284: // If scale > 0 then we must divide, if scale > 0 then we must multiply, 1285: // and if scale is zero then we just return intVal; 1286: if (scale > 0) 1287: return intVal.divide (BigInteger.TEN.pow (scale)); 1288: else if (scale < 0) 1289: return intVal.multiply(BigInteger.TEN.pow(-scale)); 1290: return intVal; 1291: } 1292: 1293: /** 1294: * Converts this BigDecimal into a BigInteger, throwing an 1295: * ArithmeticException if the conversion is not exact. 1296: * @return a BigInteger whose value is equal to the value of this BigDecimal 1297: * @since 1.5 1298: */ 1299: public BigInteger toBigIntegerExact() 1300: { 1301: if (scale > 0) 1302: { 1303: // If we have to divide, we must check if the result is exact. 1304: BigInteger[] result = 1305: intVal.divideAndRemainder(BigInteger.TEN.pow(scale)); 1306: if (result[1].equals(BigInteger.ZERO)) 1307: return result[0]; 1308: throw new ArithmeticException("No exact BigInteger representation"); 1309: } 1310: else if (scale < 0) 1311: // If we're multiplying instead, then we needn't check for exactness. 1312: return intVal.multiply(BigInteger.TEN.pow(-scale)); 1313: // If the scale is zero we can simply return intVal. 1314: return intVal; 1315: } 1316: 1317: public int intValue () 1318: { 1319: return toBigInteger ().intValue (); 1320: } 1321: 1322: /** 1323: * Returns a BigDecimal which is numerically equal to this BigDecimal but 1324: * with no trailing zeros in the representation. For example, if this 1325: * BigDecimal has [unscaledValue, scale] = [6313000, 4] this method returns 1326: * a BigDecimal with [unscaledValue, scale] = [6313, 1]. As another 1327: * example, [12400, -2] would become [124, -4]. 1328: * @return a numerically equal BigDecimal with no trailing zeros 1329: */ 1330: public BigDecimal stripTrailingZeros() 1331: { 1332: String intValStr = intVal.toString(); 1333: int newScale = scale; 1334: int pointer = intValStr.length() - 1; 1335: // This loop adjusts pointer which will be used to give us the substring 1336: // of intValStr to use in our new BigDecimal, and also accordingly 1337: // adjusts the scale of our new BigDecimal. 1338: while (intValStr.charAt(pointer) == '0') 1339: { 1340: pointer --; 1341: newScale --; 1342: } 1343: // Create a new BigDecimal with the appropriate substring and then 1344: // set its scale. 1345: BigDecimal result = new BigDecimal(intValStr.substring(0, pointer + 1)); 1346: result.scale = newScale; 1347: return result; 1348: } 1349: 1350: public long longValue () 1351: { 1352: return toBigInteger().longValue(); 1353: } 1354: 1355: public float floatValue() 1356: { 1357: return Float.valueOf(toString()).floatValue(); 1358: } 1359: 1360: public double doubleValue() 1361: { 1362: return Double.valueOf(toString()).doubleValue(); 1363: } 1364: 1365: public BigDecimal setScale (int scale) throws ArithmeticException 1366: { 1367: return setScale (scale, ROUND_UNNECESSARY); 1368: } 1369: 1370: public BigDecimal setScale (int scale, int roundingMode) 1371: throws ArithmeticException, IllegalArgumentException 1372: { 1373: // NOTE: The 1.5 JRE doesn't throw this, ones prior to it do and 1374: // the spec says it should. Nevertheless, if 1.6 doesn't fix this 1375: // we should consider removing it. 1376: if( scale < 0 ) throw new ArithmeticException("Scale parameter < 0."); 1377: return divide (ONE, scale, roundingMode); 1378: } 1379: 1380: /** 1381: * Returns a BigDecimal whose value is the same as this BigDecimal but whose 1382: * representation has a scale of <code>newScale</code>. If the scale is 1383: * reduced then rounding may occur, according to the RoundingMode. 1384: * @param newScale 1385: * @param roundingMode 1386: * @return a BigDecimal whose scale is as given, whose value is 1387: * <code>this</code> with possible rounding 1388: * @throws ArithmeticException if the rounding mode is UNNECESSARY but 1389: * rounding is required 1390: * @since 1.5 1391: */ 1392: public BigDecimal setScale(int newScale, RoundingMode roundingMode) 1393: { 1394: return setScale(newScale, roundingMode.ordinal()); 1395: } 1396: 1397: /** 1398: * Returns a new BigDecimal constructed from the BigDecimal(String) 1399: * constructor using the Double.toString(double) method to obtain 1400: * the String. 1401: * @param val the double value used in Double.toString(double) 1402: * @return a BigDecimal representation of val 1403: * @throws NumberFormatException if val is NaN or infinite 1404: * @since 1.5 1405: */ 1406: public static BigDecimal valueOf(double val) 1407: { 1408: if (Double.isInfinite(val) || Double.isNaN(val)) 1409: throw new NumberFormatException("argument cannot be NaN or infinite."); 1410: return new BigDecimal(Double.toString(val)); 1411: } 1412: 1413: /** 1414: * Returns a BigDecimal whose numerical value is the numerical value 1415: * of this BigDecimal multiplied by 10 to the power of <code>n</code>. 1416: * @param n the power of ten 1417: * @return the new BigDecimal 1418: * @since 1.5 1419: */ 1420: public BigDecimal scaleByPowerOfTen(int n) 1421: { 1422: BigDecimal result = new BigDecimal(intVal, scale - n); 1423: result.precision = precision; 1424: return result; 1425: } 1426: 1427: /** 1428: * Returns a BigDecimal whose value is <code>this</code> to the power of 1429: * <code>n</code>. 1430: * @param n the power 1431: * @return the new BigDecimal 1432: * @since 1.5 1433: */ 1434: public BigDecimal pow(int n) 1435: { 1436: if (n < 0 || n > 999999999) 1437: throw new ArithmeticException("n must be between 0 and 999999999"); 1438: BigDecimal result = new BigDecimal(intVal.pow(n), scale * n); 1439: return result; 1440: } 1441: 1442: /** 1443: * Returns a BigDecimal whose value is determined by first calling pow(n) 1444: * and then by rounding according to the MathContext mc. 1445: * @param n the power 1446: * @param mc the MathContext 1447: * @return the new BigDecimal 1448: * @throws ArithmeticException if n < 0 or n > 999999999 or if the result is 1449: * inexact but the rounding is RoundingMode.UNNECESSARY 1450: * @since 1.5 1451: */ 1452: public BigDecimal pow(int n, MathContext mc) 1453: { 1454: // FIXME: The specs claim to use the X3.274-1996 algorithm. We 1455: // currently do not. 1456: return pow(n).round(mc); 1457: } 1458: 1459: /** 1460: * Returns a BigDecimal whose value is the absolute value of this BigDecimal 1461: * with rounding according to the given MathContext. 1462: * @param mc the MathContext 1463: * @return the new BigDecimal 1464: */ 1465: public BigDecimal abs(MathContext mc) 1466: { 1467: BigDecimal result = abs(); 1468: result = result.round(mc); 1469: return result; 1470: } 1471: 1472: /** 1473: * Returns the size of a unit in the last place of this BigDecimal. This 1474: * returns a BigDecimal with [unscaledValue, scale] = [1, this.scale()]. 1475: * @return the size of a unit in the last place of <code>this</code>. 1476: * @since 1.5 1477: */ 1478: public BigDecimal ulp() 1479: { 1480: return new BigDecimal(BigInteger.ONE, scale); 1481: } 1482: 1483: /** 1484: * Converts this BigDecimal to a long value. 1485: * @return the long value 1486: * @throws ArithmeticException if rounding occurs or if overflow occurs 1487: * @since 1.5 1488: */ 1489: public long longValueExact() 1490: { 1491: // Set scale will throw an exception if rounding occurs. 1492: BigDecimal temp = setScale(0, ROUND_UNNECESSARY); 1493: BigInteger tempVal = temp.intVal; 1494: // Check for overflow. 1495: long result = intVal.longValue(); 1496: if (tempVal.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 1 1497: || (result < 0 && signum() == 1) || (result > 0 && signum() == -1)) 1498: throw new ArithmeticException("this BigDecimal is too " + 1499: "large to fit into the return type"); 1500: 1501: return intVal.longValue(); 1502: } 1503: 1504: /** 1505: * Converts this BigDecimal into an int by first calling longValueExact 1506: * and then checking that the <code>long</code> returned from that 1507: * method fits into an <code>int</code>. 1508: * @return an int whose value is <code>this</code> 1509: * @throws ArithmeticException if this BigDecimal has a fractional part 1510: * or is too large to fit into an int. 1511: * @since 1.5 1512: */ 1513: public int intValueExact() 1514: { 1515: long temp = longValueExact(); 1516: int result = (int)temp; 1517: if (result != temp) 1518: throw new ArithmeticException ("this BigDecimal cannot fit into an int"); 1519: return result; 1520: } 1521: 1522: /** 1523: * Converts this BigDecimal into a byte by first calling longValueExact 1524: * and then checking that the <code>long</code> returned from that 1525: * method fits into a <code>byte</code>. 1526: * @return a byte whose value is <code>this</code> 1527: * @throws ArithmeticException if this BigDecimal has a fractional part 1528: * or is too large to fit into a byte. 1529: * @since 1.5 1530: */ 1531: public byte byteValueExact() 1532: { 1533: long temp = longValueExact(); 1534: byte result = (byte)temp; 1535: if (result != temp) 1536: throw new ArithmeticException ("this BigDecimal cannot fit into a byte"); 1537: return result; 1538: } 1539: 1540: /** 1541: * Converts this BigDecimal into a short by first calling longValueExact 1542: * and then checking that the <code>long</code> returned from that 1543: * method fits into a <code>short</code>. 1544: * @return a short whose value is <code>this</code> 1545: * @throws ArithmeticException if this BigDecimal has a fractional part 1546: * or is too large to fit into a short. 1547: * @since 1.5 1548: */ 1549: public short shortValueExact() 1550: { 1551: long temp = longValueExact(); 1552: short result = (short)temp; 1553: if (result != temp) 1554: throw new ArithmeticException ("this BigDecimal cannot fit into a short"); 1555: return result; 1556: } 1557: }
GNU Classpath (0.95) |