1 18 19 package com.Ostermiller.util; 20 21 86 public class SignificantFigures extends Number { 87 88 95 private String original; 96 101 private StringBuffer digits; 102 109 private int mantissa = -1; 110 115 private boolean sign = true; 116 121 private boolean isZero = false; 122 123 131 public SignificantFigures(String number) throws NumberFormatException { 132 original = number; 133 parse(original); 134 } 135 136 143 public SignificantFigures(byte number){ 144 original = Byte.toString(number); 145 try { 146 parse(original); 147 } catch (NumberFormatException nfe){ 148 digits = null; 149 } 150 } 151 152 159 public SignificantFigures(short number){ 160 original = Short.toString(number); 161 try { 162 parse(original); 163 } catch (NumberFormatException nfe){ 164 digits = null; 165 } 166 } 167 168 175 public SignificantFigures(int number){ 176 original = String.valueOf(number); 177 try { 178 parse(original); 179 } catch (NumberFormatException nfe){ 180 digits = null; 181 } 182 } 183 184 191 public SignificantFigures(long number){ 192 original = Long.toString(number); 193 try { 194 parse(original); 195 } catch (NumberFormatException nfe){ 196 digits = null; 197 } 198 } 199 200 207 public SignificantFigures(float number){ 208 original = Float.toString(number); 209 try { 210 parse(original); 211 } catch (NumberFormatException nfe){ 212 digits = null; 213 } 214 } 215 216 223 public SignificantFigures(double number){ 224 original = Double.toString(number); 225 try { 226 parse(original); 227 } catch (NumberFormatException nfe){ 228 digits = null; 229 } 230 } 231 232 241 public SignificantFigures(Number number){ 242 original = number.toString(); 243 try { 244 parse(original); 245 } catch (NumberFormatException nfe){ 246 digits = null; 247 } 248 } 249 250 276 277 287 public int getNumberSignificantFigures() { 288 if (digits == null) return 0; 289 return digits.length(); 290 } 291 292 313 public SignificantFigures setLSD(int place){ 314 setLMSD(place, Integer.MIN_VALUE); 315 return this; 316 } 317 318 336 public SignificantFigures setLMSD(int leastPlace, int mostPlace){ 337 if (digits != null && leastPlace != Integer.MIN_VALUE){ 338 int significantFigures = digits.length(); 339 int current = mantissa - significantFigures + 1; 340 int newLength = significantFigures - leastPlace + current; 341 if (newLength <= 0){ 342 if (mostPlace == Integer.MIN_VALUE){ 343 original = "NaN"; 344 digits = null; 345 } else { 346 newLength = mostPlace - leastPlace + 1; 347 digits.setLength(newLength); 348 mantissa = leastPlace; 349 for (int i=0; i<newLength; i++){ 350 digits.setCharAt(i, '0'); 351 } 352 isZero = true; 353 sign = true; 354 } 355 } else { 356 digits.setLength(newLength); 357 for (int i=significantFigures; i<newLength; i++){ 358 digits.setCharAt(i, '0'); 359 } 360 } 361 } 362 return this; 363 } 364 365 375 public int getLSD(){ 376 if (digits == null) return Integer.MIN_VALUE; 377 return mantissa - digits.length() + 1; 378 } 379 380 390 public int getMSD(){ 391 if (digits == null) return Integer.MIN_VALUE; 392 return mantissa + 1; 393 } 394 395 407 public String toString() { 408 if (digits == null) return original; 409 StringBuffer digits = new StringBuffer (this.digits.toString()); 410 int length = digits.length(); 411 if (mantissa <= -4 || mantissa >= 7 || 412 (mantissa >= length && 413 digits.charAt(digits.length()-1) == '0') || 414 (isZero && mantissa != 0)) { 415 if (length > 1){ 417 digits.insert(1, '.'); 418 } 419 if (mantissa != 0){ 420 digits.append("E" + mantissa); 421 } 422 } else if (mantissa <= -1){ 423 digits.insert(0, "0."); 424 for (int i=mantissa; i<-1; i++){ 425 digits.insert(2, '0'); 426 } 427 } else if (mantissa+1 == length){ 428 if (length > 1 && digits.charAt(digits.length()-1) == '0'){ 429 digits.append('.'); 430 } 431 } else if (mantissa < length){ 432 digits.insert(mantissa+1, '.'); 433 } else { 434 for (int i=length; i<=mantissa; i++){ 435 digits.append('0'); 436 } 437 } 438 if (!sign) { 439 digits.insert(0, '-'); 440 } 441 return digits.toString(); 442 } 443 444 453 public String toScientificNotation() { 454 if (digits == null) return original; 455 StringBuffer digits = new StringBuffer (this.digits.toString()); 456 int length = digits.length(); 457 if (length > 1){ 458 digits.insert(1, '.'); 459 } 460 if (mantissa != 0){ 461 digits.append("E" + mantissa); 462 } 463 if (!sign) { 464 digits.insert(0, '-'); 465 } 466 return digits.toString(); 467 } 468 469 475 private final static int INITIAL = 0; 476 483 private final static int LEADZEROS = 1; 484 494 private final static int MIDZEROS = 2; 495 504 private final static int DIGITS = 3; 505 513 private final static int LEADZEROSDOT = 4; 514 522 private final static int DIGITSDOT = 5; 523 530 private final static int MANTISSA = 6; 531 540 private final static int MANTISSADIGIT = 7; 541 542 554 private void parse(String number) throws NumberFormatException { 555 int length = number.length(); 556 digits = new StringBuffer (length); 557 int state = INITIAL; 558 int mantissaStart = -1; 559 boolean foundMantissaDigit = false; 560 int zeroCount = 0; 566 int leadZeroCount = 0; 567 568 for (int i=0; i<length; i++){ 569 char c = number.charAt(i); 570 switch (c){ 571 case '.': { 572 switch (state){ 573 case INITIAL: 574 case LEADZEROS: { 575 state = LEADZEROSDOT; 576 } break; 577 case MIDZEROS: { 578 for (int j=0; j<zeroCount; j++){ 581 digits.append('0'); 582 } 583 zeroCount = 0; 584 state = DIGITSDOT; 585 } break; 586 case DIGITS: { 587 state = DIGITSDOT; 588 } break; 589 default: { 590 throw new NumberFormatException ( 591 "Unexpected character '" + c + "' at position " + i 592 ); 593 } 594 } 595 } break; 596 case '+':{ 597 switch (state){ 598 case INITIAL: { 599 sign = true; 600 state = LEADZEROS; 601 } break; 602 case MANTISSA: { 603 state = MANTISSADIGIT; 604 } break; 605 default: { 606 throw new NumberFormatException ( 607 "Unexpected character '" + c + "' at position " + i 608 ); 609 } 610 } 611 } break; 612 case '-': { 613 switch (state){ 614 case INITIAL: { 615 sign = false; 616 state = LEADZEROS; 617 } break; 618 case MANTISSA: { 619 state = MANTISSADIGIT; 620 } break; 621 default: { 622 throw new NumberFormatException ( 623 "Unexpected character '" + c + "' at position " + i 624 ); 625 } 626 } 627 } break; 628 case '0': { 629 switch (state){ 630 case INITIAL: 631 case LEADZEROS: { 632 zeroCount++; 635 leadZeroCount++; 636 state = LEADZEROS; 637 } break; 638 case MIDZEROS: 639 case DIGITS: { 640 mantissa++; 643 zeroCount++; 644 state = MIDZEROS; 645 } break; 646 case LEADZEROSDOT:{ 647 mantissa--; 650 zeroCount++; 651 state = LEADZEROSDOT; 652 } break; 653 case DIGITSDOT: { 654 digits.append(c); 658 } break; 659 case MANTISSA: 660 case MANTISSADIGIT: { 661 foundMantissaDigit = true; 662 state = MANTISSADIGIT; 663 } break; 664 default: { 665 throw new NumberFormatException ( 666 "Unexpected character '" + c + "' at position " + i 667 ); 668 } 669 } 670 } break; 671 case '1': case '2': case '3': 672 case '4': case '5': case '6': 673 case '7': case '8': case '9': { 674 switch (state){ 675 case INITIAL: 676 case LEADZEROS: 677 case DIGITS: { 678 zeroCount = 0; 679 digits.append(c); 680 mantissa++; 681 state = DIGITS; 682 } break; 683 case MIDZEROS: { 684 for (int j=0; j<zeroCount; j++){ 687 digits.append('0'); 688 } 689 zeroCount = 0; 690 digits.append(c); 691 mantissa++; 692 state = DIGITS; 693 } break; 694 case LEADZEROSDOT: 695 case DIGITSDOT: { 696 zeroCount = 0; 697 digits.append(c); 698 state = DIGITSDOT; 699 } break; 700 case MANTISSA: 701 case MANTISSADIGIT: { 702 state = MANTISSADIGIT; 703 foundMantissaDigit = true; 704 } break; 705 default: { 706 throw new NumberFormatException ( 707 "Unexpected character '" + c + "' at position " + i 708 ); 709 } 710 } 711 } break; 712 case 'E': case 'e': { 713 switch (state){ 714 case INITIAL: 715 case LEADZEROS: 716 case DIGITS: 717 case LEADZEROSDOT: 718 case DIGITSDOT: { 719 mantissaStart = i+1; 722 state = MANTISSA; 723 } break; 724 default: { 725 throw new NumberFormatException ( 726 "Unexpected character '" + c + "' at position " + i 727 ); 728 } 729 } 730 } break; 731 default: { 732 throw new NumberFormatException ( 733 "Unexpected character '" + c + "' at position " + i 734 ); 735 } 736 } 737 } 738 if (mantissaStart != -1){ 739 if (!foundMantissaDigit){ 741 throw new NumberFormatException ( 743 "No digits in mantissa." 744 ); 745 } 746 mantissa += Integer.parseInt(number.substring(mantissaStart)); 748 } 749 if (digits.length() == 0){ 750 if (zeroCount > 0){ 751 for (int j=0; j<zeroCount; j++){ 753 digits.append('0'); 754 } 755 mantissa += leadZeroCount; 756 isZero = true; 757 sign = true; 758 } else { 759 throw new NumberFormatException ( 763 "No digits in number." 764 ); 765 } 766 } 767 } 768 769 782 public SignificantFigures setNumberSignificantFigures(int significantFigures){ 783 if (significantFigures <= 0) throw new IllegalArgumentException ("Desired number of significant figures must be positive."); 784 if (digits != null) { 785 int length = digits.length(); 786 if (length < significantFigures){ 787 for (int i=length; i<significantFigures; i++){ 789 digits.append('0'); 790 } 791 } else if (length > significantFigures){ 792 boolean addOne; char firstInSig = digits.charAt(significantFigures); 795 if (firstInSig < '5'){ 796 addOne = false; 798 } else if (firstInSig == '5'){ 799 addOne = false; 801 for (int i=significantFigures+1; !addOne && i<length; i++){ 802 if (digits.charAt(i) != '0'){ 804 addOne = true; 805 } 806 } 807 if (!addOne){ 808 addOne = (digits.charAt(significantFigures-1) & 1) == 1; 812 } 813 } else { 814 addOne = true; 816 } 817 for (int i=significantFigures-1; addOne && i>=0; i--){ 820 char digit = digits.charAt(i); 821 if (digit < '9'){ 822 digits.setCharAt(i, (char)(digit+1)); 823 addOne = false; 824 } else { 825 digits.setCharAt(i, '0'); 826 } 827 } 828 if (addOne){ 829 digits.insert(0, '1'); 831 mantissa++; 832 } 833 digits.setLength(significantFigures); 835 } 836 } 837 return this; 838 } 839 840 848 public byte byteValue() throws NumberFormatException { 849 return Byte.parseByte(original); 850 } 851 852 860 public double doubleValue() throws NumberFormatException { 861 return Double.parseDouble(original); 862 } 863 864 872 public float floatValue() throws NumberFormatException { 873 return Float.parseFloat(original); 874 } 875 876 884 public int intValue() throws NumberFormatException { 885 return Integer.parseInt(original); 886 } 887 888 896 public long longValue() throws NumberFormatException { 897 return Long.parseLong(original); 898 } 899 900 908 public short shortValue() throws NumberFormatException { 909 return Short.parseShort(original); 910 } 911 912 921 public static String format(byte number, int significantFigures){ 922 SignificantFigures sf = new SignificantFigures(number); 923 sf.setNumberSignificantFigures(significantFigures); 924 return sf.toString(); 925 } 926 927 936 public static String format(double number, int significantFigures){ 937 SignificantFigures sf = new SignificantFigures(number); 938 sf.setNumberSignificantFigures(significantFigures); 939 return sf.toString(); 940 } 941 942 951 public static String format(float number, int significantFigures){ 952 SignificantFigures sf = new SignificantFigures(number); 953 sf.setNumberSignificantFigures(significantFigures); 954 return sf.toString(); 955 } 956 957 966 public static String format(int number, int significantFigures){ 967 SignificantFigures sf = new SignificantFigures(number); 968 sf.setNumberSignificantFigures(significantFigures); 969 return sf.toString(); 970 } 971 972 981 public static String format(long number, int significantFigures){ 982 SignificantFigures sf = new SignificantFigures(number); 983 sf.setNumberSignificantFigures(significantFigures); 984 return sf.toString(); 985 } 986 987 996 public static String format(Number number, int significantFigures){ 997 SignificantFigures sf = new SignificantFigures(number); 998 sf.setNumberSignificantFigures(significantFigures); 999 return sf.toString(); 1000 } 1001 1002 1011 public static String format(short number, int significantFigures){ 1012 SignificantFigures sf = new SignificantFigures(number); 1013 sf.setNumberSignificantFigures(significantFigures); 1014 return sf.toString(); 1015 } 1016 1017 1027 public static String format(String number, int significantFigures) throws NumberFormatException { 1028 SignificantFigures sf = new SignificantFigures(number); 1029 sf.setNumberSignificantFigures(significantFigures); 1030 return sf.toString(); 1031 } 1032} 1033 | Popular Tags |