| 1 7 8 18 19 package java.math; 20 21 205 public class BigDecimal extends Number implements Comparable <BigDecimal > { 206 213 private volatile BigInteger intVal; 214 215 221 private int scale = 0; 232 private volatile transient int precision = 0; 233 234 237 private volatile transient String stringCache = null; 238 239 243 private static final long INFLATED = Long.MIN_VALUE; 244 245 250 private transient long intCompact = INFLATED; 251 252 private static final int MAX_COMPACT_DIGITS = 18; 255 256 private static final int MAX_BIGINT_BITS = 62; 257 258 259 private static final long serialVersionUID = 6108874887143696463L; 260 261 private static final BigDecimal zeroThroughTen[] = { 263 new BigDecimal (BigInteger.ZERO, 0, 0), 264 new BigDecimal (BigInteger.ONE, 1, 0), 265 new BigDecimal (BigInteger.valueOf(2), 2, 0), 266 new BigDecimal (BigInteger.valueOf(3), 3, 0), 267 new BigDecimal (BigInteger.valueOf(4), 4, 0), 268 new BigDecimal (BigInteger.valueOf(5), 5, 0), 269 new BigDecimal (BigInteger.valueOf(6), 6, 0), 270 new BigDecimal (BigInteger.valueOf(7), 7, 0), 271 new BigDecimal (BigInteger.valueOf(8), 8, 0), 272 new BigDecimal (BigInteger.valueOf(9), 9, 0), 273 new BigDecimal (BigInteger.TEN, 10, 0), 274 }; 275 276 282 public static final BigDecimal ZERO = 283 zeroThroughTen[0]; 284 285 290 public static final BigDecimal ONE = 291 zeroThroughTen[1]; 292 293 298 public static final BigDecimal TEN = 299 zeroThroughTen[10]; 300 301 303 322 public BigDecimal(char[] in, int offset, int len) { 323 328 try { 331 boolean isneg = false; if (in[offset] == '-') { 334 isneg = true; offset++; 336 len--; 337 } else if (in[offset] == '+') { offset++; 339 len--; 340 } 341 342 int dotoff = -1; int cfirst = offset; long exp = 0; if (len > in.length) throw new NumberFormatException (); 348 char coeff[] = new char[len]; char c; 351 for (; len > 0; offset++, len--) { 352 c = in[offset]; 353 if ((c >= '0' && c <= '9') || Character.isDigit(c)) { 354 coeff[precision] = c; 356 precision++; continue; 358 } 359 if (c == '.') { 360 if (dotoff >= 0) throw new NumberFormatException (); 363 dotoff = offset; 364 continue; 365 } 366 if ((c != 'e') && (c != 'E')) 368 throw new NumberFormatException (); 369 offset++; 370 c = in[offset]; 371 len--; 372 boolean negexp = false; 373 if (c == '-' || c == '+') { 375 negexp = (c == '-'); 376 offset++; 377 c = in[offset]; 378 len--; 379 } 380 if (len <= 0) throw new NumberFormatException (); 382 while (len > 10 && Character.digit(c, 10) == 0) { 384 offset++; 385 c = in[offset]; 386 len--; 387 } 388 if (len > 10) throw new NumberFormatException (); 390 for (;; len--) { 392 int v; 393 if (c >= '0' && c <= '9') { 394 v = c - '0'; 395 } else { 396 v = Character.digit(c, 10); 397 if (v < 0) throw new NumberFormatException (); 399 } 400 exp = exp * 10 + v; 401 if (len == 1) 402 break; offset++; 404 c = in[offset]; 405 } 406 if (negexp) exp = -exp; 408 if ((int)exp != exp) throw new NumberFormatException (); 411 break; } 413 if (precision == 0) throw new NumberFormatException (); 416 417 if (dotoff >= 0) { scale = precision - (dotoff - cfirst); 419 } 421 if (exp != 0) { try { 423 scale = checkScale(-exp + scale); } catch (ArithmeticException e) { 425 throw new NumberFormatException ("Scale out of range."); 426 } 427 } 428 429 int first = 0; 431 for (; (coeff[first] == '0' || Character.digit(coeff[first], 10) == 0) && 432 precision > 1; 433 first++) 434 precision--; 435 436 char quick[]; 443 if (!isneg) { 444 quick = new char[precision]; 445 System.arraycopy(coeff, first, quick, 0, precision); 446 } else { 447 quick = new char[precision+1]; 448 quick[0] = '-'; 449 System.arraycopy(coeff, first, quick, 1, precision); 450 } 451 if (precision <= MAX_COMPACT_DIGITS) 452 intCompact = Long.parseLong(new String (quick)); 453 else 454 intVal = new BigInteger (quick); 455 } catch (ArrayIndexOutOfBoundsException e) { 457 throw new NumberFormatException (); 458 } catch (NegativeArraySizeException e) { 459 throw new NumberFormatException (); 460 } 461 } 462 463 486 public BigDecimal(char[] in, int offset, int len, MathContext mc) { 487 this(in, offset, len); 488 if (mc.precision > 0) 489 roundThis(mc); 490 } 491 492 508 public BigDecimal(char[] in) { 509 this(in, 0, in.length); 510 } 511 512 532 public BigDecimal(char[] in, MathContext mc) { 533 this(in, 0, in.length, mc); 534 } 535 536 646 public BigDecimal(String val) { 647 this(val.toCharArray(), 0, val.length()); 648 } 649 650 664 public BigDecimal(String val, MathContext mc) { 665 this(val.toCharArray(), 0, val.length()); 666 if (mc.precision > 0) 667 roundThis(mc); 668 } 669 670 714 public BigDecimal(double val) { 715 if (Double.isInfinite(val) || Double.isNaN(val)) 716 throw new NumberFormatException ("Infinite or NaN"); 717 718 long valBits = Double.doubleToLongBits(val); 721 int sign = ((valBits >> 63)==0 ? 1 : -1); 722 int exponent = (int) ((valBits >> 52) & 0x7ffL); 723 long significand = (exponent==0 ? (valBits & ((1L<<52) - 1)) << 1 724 : (valBits & ((1L<<52) - 1)) | (1L<<52)); 725 exponent -= 1075; 726 728 732 if (significand == 0) { 733 intVal = BigInteger.ZERO; 734 intCompact = 0; 735 precision = 1; 736 return; 737 } 738 739 while((significand & 1) == 0) { significand >>= 1; 742 exponent++; 743 } 744 745 intVal = BigInteger.valueOf(sign*significand); 747 if (exponent < 0) { 748 intVal = intVal.multiply(BigInteger.valueOf(5).pow(-exponent)); 749 scale = -exponent; 750 } else if (exponent > 0) { 751 intVal = intVal.multiply(BigInteger.valueOf(2).pow(exponent)); 752 } 753 if (intVal.bitLength() <= MAX_BIGINT_BITS) { 754 intCompact = intVal.longValue(); 755 } 756 } 757 758 776 public BigDecimal(double val, MathContext mc) { 777 this(val); 778 if (mc.precision > 0) 779 roundThis(mc); 780 } 781 782 789 public BigDecimal(BigInteger val) { 790 intVal = val; 791 if (val.bitLength() <= MAX_BIGINT_BITS) { 792 intCompact = val.longValue(); 793 } 794 } 795 796 808 public BigDecimal(BigInteger val, MathContext mc) { 809 intVal = val; 810 if (mc.precision > 0) 811 roundThis(mc); 812 } 813 814 823 public BigDecimal(BigInteger unscaledVal, int scale) { 824 intVal = unscaledVal; 826 this.scale = scale; 827 if (unscaledVal.bitLength() <= MAX_BIGINT_BITS) { 828 intCompact = unscaledVal.longValue(); 829 } 830 } 831 832 847 public BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) { 848 intVal = unscaledVal; 849 this.scale = scale; 850 if (mc.precision > 0) 851 roundThis(mc); 852 } 853 854 862 public BigDecimal(int val) { 863 intCompact = val; 864 } 865 866 877 public BigDecimal(int val, MathContext mc) { 878 intCompact = val; 879 if (mc.precision > 0) 880 roundThis(mc); 881 } 882 883 890 public BigDecimal(long val) { 891 if (compactLong(val)) 892 intCompact = val; 893 else 894 intVal = BigInteger.valueOf(val); 895 } 896 897 908 public BigDecimal(long val, MathContext mc) { 909 if (compactLong(val)) 910 intCompact = val; 911 else 912 intVal = BigInteger.valueOf(val); 913 if (mc.precision > 0) 914 roundThis(mc); 915 } 916 917 920 private BigDecimal(long val, int scale) { 921 this.intCompact = val; 922 this.scale = scale; 923 } 924 925 928 private BigDecimal(BigInteger intVal, long val, int scale) { 929 this.intVal = intVal; 930 this.intCompact = val; 931 this.scale = scale; 932 } 933 934 936 |