Source Code Cross Referenced for SignificantFigures.java in  » Template-Engine » ostermillerutils » com » Ostermiller » util » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Template Engine » ostermillerutils » com.Ostermiller.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (C) 2002-2007 Stephen Ostermiller
0003:         * http://ostermiller.org/contact.pl?regarding=Java+Utilities
0004:         *
0005:         * This program is free software; you can redistribute it and/or modify
0006:         * it under the terms of the GNU General Public License as published by
0007:         * the Free Software Foundation; either version 2 of the License, or
0008:         * (at your option) any later version.
0009:         *
0010:         * This program is distributed in the hope that it will be useful,
0011:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013:         * GNU General Public License for more details.
0014:         *
0015:         * See COPYING.TXT for details.
0016:         */
0017:
0018:        package com.Ostermiller.util;
0019:
0020:        /**
0021:         * A number with an associated number of significant figures.
0022:         * This class handles parsing numbers, determining the number
0023:         * of significant figures, adjusting the number of significant
0024:         * figures (including scientific rounding), and displaying the number.
0025:         * More information about this class is available from <a target="_top" href=
0026:         * "http://ostermiller.org/utils/SignificantFigures.html">ostermiller.org</a>.
0027:         * <p>
0028:         * When parsing a number to determine the number of significant figures,
0029:         * these rules are used:
0030:         * <ul>
0031:         * <li>Non-zero digits are always significant.</li>
0032:         * <li>All zeros between other significant digits are significant.</li>
0033:         * <li>All zeros left of the decimal point between a significant digit and the decimal point are significant.</li>
0034:         * <li>All trailing zeros to the right of the decimal point are significant.</li>
0035:         * <li>If the number is contains no digits other than zero, every zero is significant.</li>
0036:         * </ul>
0037:         * <p>
0038:         * When rounding a number the following rules are used:
0039:         * <ul>
0040:         * <li>If the greatest insignificant digit is less than five, round down.</li>
0041:         * <li>If the greatest insignificant digit is greater than five, round up.</li>
0042:         * <li>If the greatest insignificant digit is five and followed by some non-zero digit, round up.</li>
0043:         * <li>If the greatest insignificant digit is five and followed only by zeros, and the least significant
0044:         * digit is odd, round up.</li>
0045:         * <li>If the greatest insignificant digit is five and followed only by zeros, and the least significant
0046:         * digit is even, round down.</li>
0047:         * </ul>
0048:         *
0049:         * <p>
0050:         * Example of using this class to multiply numbers and display the result
0051:         * with the proper number of significant figures:<br>
0052:         * <pre> String[] arguments = {"1.0", "2.0", ...}
0053:         * SignificantFigures number;
0054:         * int sigFigs = Integer.MAX_VALUE;
0055:         * double result = 1D;
0056:         * for (int i=0; i&lt;arguments.length; i++){
0057:         * &nbsp;   number = new SignificantFigures(arguments[i]);
0058:         * &nbsp;   sigFigs = Math.min(sigFigs, number.getNumberSignificantFigures());
0059:         * &nbsp;   result *= number.doubleValue();
0060:         * }
0061:         * number = new SignificantFigures(result);
0062:         * number.setNumberSignificantFigures(sigFigs);
0063:         * System.out.println(number);</pre>
0064:         * <p>
0065:         * Example of using this class to add numbers and display the result
0066:         * with the proper number of significant figures:<br>
0067:         * <pre> String[] arguments = {"1.0", "2.0", ...}
0068:         * SignificantFigures number;
0069:         * int leastSD = Integer.MIN_VALUE;
0070:         * int mostSD = Integer.MIN_VALUE;
0071:         * double result = 0D;
0072:         * for (int i=0; i&lt;arguments.length; i++){
0073:         * &nbsp;   number = new SignificantFigures(arguments[i]);
0074:         * &nbsp;   leastSD = Math.max(leastSD, number.getLSD());
0075:         * &nbsp;   mostSD = Math.max(mostSD, number.getMSD());
0076:         * &nbsp;   result += number.doubleValue();
0077:         * }
0078:         * number = new SignificantFigures(result);
0079:         * number.setLMSD(leastSD, mostSD);
0080:         * System.out.println(number);</pre>
0081:         *
0082:         * @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities
0083:         * @since ostermillerutils 1.00.00
0084:         */
0085:        public class SignificantFigures extends Number {
0086:
0087:            /**
0088:             *
0089:             */
0090:            private static final long serialVersionUID = -1130798283937219608L;
0091:            /**
0092:             * In the case the a number
0093:             * could not be parsed, the original is stored
0094:             * for toString purposes.
0095:             *
0096:             * @since ostermillerutils 1.00.00
0097:             */
0098:            private String original;
0099:            /**
0100:             * Buffer of the significant digits.
0101:             *
0102:             * @since ostermillerutils 1.00.00
0103:             */
0104:            private StringBuffer digits;
0105:            /**
0106:             * The exponent of the digits if a
0107:             * decimal place were inserted after
0108:             * the first digit.
0109:             *
0110:             * @since ostermillerutils 1.00.00
0111:             */
0112:            private int mantissa = -1;
0113:            /**
0114:             * positive if true, negative if false.
0115:             *
0116:             * @since ostermillerutils 1.00.00
0117:             */
0118:            private boolean sign = true;
0119:            /**
0120:             * True if this number has no non-zero digits.
0121:             *
0122:             * @since ostermillerutils 1.00.00
0123:             */
0124:            private boolean isZero = false;
0125:
0126:            /**
0127:             * Create a SignificantFigures object from a String representation of a number.
0128:             *
0129:             * @param number String representation of the number.
0130:             * @throws NumberFormatException if the String is not a valid number.
0131:             *
0132:             * @since ostermillerutils 1.00.00
0133:             */
0134:            public SignificantFigures(String number)
0135:                    throws NumberFormatException {
0136:                original = number;
0137:                parse(original);
0138:            }
0139:
0140:            /**
0141:             * Create a SignificantFigures object from a byte.
0142:             *
0143:             * @param number an 8 bit integer.
0144:             *
0145:             * @since ostermillerutils 1.00.00
0146:             */
0147:            public SignificantFigures(byte number) {
0148:                original = Byte.toString(number);
0149:                try {
0150:                    parse(original);
0151:                } catch (NumberFormatException nfe) {
0152:                    digits = null;
0153:                }
0154:            }
0155:
0156:            /**
0157:             * Create a SignificantFigures object from a short.
0158:             *
0159:             * @param number a 16 bit integer.
0160:             *
0161:             * @since ostermillerutils 1.00.00
0162:             */
0163:            public SignificantFigures(short number) {
0164:                original = Short.toString(number);
0165:                try {
0166:                    parse(original);
0167:                } catch (NumberFormatException nfe) {
0168:                    digits = null;
0169:                }
0170:            }
0171:
0172:            /**
0173:             * Create a SignificantFigures object from an integer.
0174:             *
0175:             * @param number a 32 bit integer.
0176:             *
0177:             * @since ostermillerutils 1.00.00
0178:             */
0179:            public SignificantFigures(int number) {
0180:                original = String.valueOf(number);
0181:                try {
0182:                    parse(original);
0183:                } catch (NumberFormatException nfe) {
0184:                    digits = null;
0185:                }
0186:            }
0187:
0188:            /**
0189:             * Create a SignificantFigures object from a long.
0190:             *
0191:             * @param number a 64 bit integer.
0192:             *
0193:             * @since ostermillerutils 1.00.00
0194:             */
0195:            public SignificantFigures(long number) {
0196:                original = Long.toString(number);
0197:                try {
0198:                    parse(original);
0199:                } catch (NumberFormatException nfe) {
0200:                    digits = null;
0201:                }
0202:            }
0203:
0204:            /**
0205:             * Create a SignificantFigures object from a float.
0206:             *
0207:             * @param number a 32 bit floating point.
0208:             *
0209:             * @since ostermillerutils 1.00.00
0210:             */
0211:            public SignificantFigures(float number) {
0212:                original = Float.toString(number);
0213:                try {
0214:                    parse(original);
0215:                } catch (NumberFormatException nfe) {
0216:                    digits = null;
0217:                }
0218:            }
0219:
0220:            /**
0221:             * Create a SignificantFigures object from a double.
0222:             *
0223:             * @param number a 64 bit floating point.
0224:             *
0225:             * @since ostermillerutils 1.00.00
0226:             */
0227:            public SignificantFigures(double number) {
0228:                original = Double.toString(number);
0229:                try {
0230:                    parse(original);
0231:                } catch (NumberFormatException nfe) {
0232:                    digits = null;
0233:                }
0234:            }
0235:
0236:            /**
0237:             * Create a SignificantFigures object from a java number such as
0238:             * a BigDecimal, BigInteger, Byte, Double, Float, Integer, Long, or
0239:             * Short.
0240:             *
0241:             * @param number a number.
0242:             *
0243:             * @since ostermillerutils 1.00.00
0244:             */
0245:            public SignificantFigures(Number number) {
0246:                original = number.toString();
0247:                try {
0248:                    parse(original);
0249:                } catch (NumberFormatException nfe) {
0250:                    digits = null;
0251:                }
0252:            }
0253:
0254:            /**
0255:             * Get the number of significant digits.
0256:             * <p>
0257:             * If this number is not a number or infinity zero
0258:             * will be returned.
0259:             *
0260:             * @return the number of significant digits in this number.
0261:             *
0262:             * @since ostermillerutils 1.00.00
0263:             */
0264:            public int getNumberSignificantFigures() {
0265:                if (digits == null)
0266:                    return 0;
0267:                return digits.length();
0268:            }
0269:
0270:            /**
0271:             * Adjust the number of significant figures such that the least
0272:             * significant digit is at the given place.  This method may add
0273:             * significant zeros to the end of this number, or remove significant
0274:             * digits from this number.
0275:             * <p>
0276:             * It is possible to remove all significant digits from this number which
0277:             * will cause the string representation of this number to become "NaN".  This
0278:             * could become a problem if you are adding numbers and the result is close
0279:             * to zero.  All of the significant digits may get removed, even though the
0280:             * result could be zero with some number of significant digits.  Its is safes
0281:             * to use the setLMSD() method which will make a zero with the appropriate
0282:             * number of significant figures in such instances.
0283:             * <p>
0284:             * This method has no effect if this number is not a number or infinity.
0285:             *
0286:             * @param place the desired place of the least significant digit.
0287:             * @return this number.
0288:             *
0289:             * @since ostermillerutils 1.00.00
0290:             */
0291:            public SignificantFigures setLSD(int place) {
0292:                setLMSD(place, Integer.MIN_VALUE);
0293:                return this ;
0294:            }
0295:
0296:            /**
0297:             * Adjust the number of significant figures such that the least
0298:             * significant digit is at the given place.  This method may add
0299:             * significant zeros to the end of this number, or remove significant
0300:             * digits from this number.
0301:             * <p>
0302:             * If all significant digits are removed from this number by truncating to
0303:             * the least significant place, a zero will be created with significant figures
0304:             * from the least to most significant places.
0305:             * <p>
0306:             * This method has no effect if this number is not a number or infinity.
0307:             *
0308:             * @param leastPlace the desired place of the least significant digit or Integer.MIN_VALUE to ignore.
0309:             * @param mostPlace the desired place of the most significant digit or Integer.MIN_VALUE to ignore.
0310:             * @return this number
0311:             *
0312:             * @since ostermillerutils 1.00.00
0313:             */
0314:            public SignificantFigures setLMSD(int leastPlace, int mostPlace) {
0315:                if (digits != null && leastPlace != Integer.MIN_VALUE) {
0316:                    int significantFigures = digits.length();
0317:                    int current = mantissa - significantFigures + 1;
0318:                    int newLength = significantFigures - leastPlace + current;
0319:                    if (newLength <= 0) {
0320:                        if (mostPlace == Integer.MIN_VALUE) {
0321:                            original = "NaN";
0322:                            digits = null;
0323:                        } else {
0324:                            newLength = mostPlace - leastPlace + 1;
0325:                            digits.setLength(newLength);
0326:                            mantissa = leastPlace;
0327:                            for (int i = 0; i < newLength; i++) {
0328:                                digits.setCharAt(i, '0');
0329:                            }
0330:                            isZero = true;
0331:                            sign = true;
0332:                        }
0333:                    } else {
0334:                        digits.setLength(newLength);
0335:                        for (int i = significantFigures; i < newLength; i++) {
0336:                            digits.setCharAt(i, '0');
0337:                        }
0338:                    }
0339:                }
0340:                return this ;
0341:            }
0342:
0343:            /**
0344:             * Get the decimal place of the least significant digit.
0345:             * <p>
0346:             * If this number is not a number or infinity Integer.MIN_VALUE
0347:             * will be returned.
0348:             *
0349:             * @return the decimal place of the least significant digit.
0350:             *
0351:             * @since ostermillerutils 1.00.00
0352:             */
0353:            public int getLSD() {
0354:                if (digits == null)
0355:                    return Integer.MIN_VALUE;
0356:                return mantissa - digits.length() + 1;
0357:            }
0358:
0359:            /**
0360:             * Get the decimal place of the most significant digit.
0361:             * <p>
0362:             * If this number is not a number or infinity Integer.MIN_VALUE
0363:             * will be returned.
0364:             *
0365:             * @return the decimal place of the least significant digit.
0366:             *
0367:             * @since ostermillerutils 1.00.00
0368:             */
0369:            public int getMSD() {
0370:                if (digits == null)
0371:                    return Integer.MIN_VALUE;
0372:                return mantissa + 1;
0373:            }
0374:
0375:            /**
0376:             * Formats this number.
0377:             * If the number is less than 10^-3 or greater than or equal to 10^7,
0378:             * or the number might have an ambiguous number of significant figures,
0379:             * scientific notation will be used.
0380:             * <p>
0381:             * A string such as "NaN" or "Infinity" may be returned by this method.
0382:             *
0383:             * @return representation of this number.
0384:             *
0385:             * @since ostermillerutils 1.00.00
0386:             */
0387:            @Override
0388:            public String toString() {
0389:                if (digits == null)
0390:                    return original;
0391:                StringBuffer digits = new StringBuffer(this .digits.toString());
0392:                int length = digits.length();
0393:                if (mantissa <= -4
0394:                        || mantissa >= 7
0395:                        || (mantissa >= length && digits
0396:                                .charAt(digits.length() - 1) == '0')
0397:                        || (isZero && mantissa != 0)) {
0398:                    // use scientific notation.
0399:                    if (length > 1) {
0400:                        digits.insert(1, '.');
0401:                    }
0402:                    if (mantissa != 0) {
0403:                        digits.append("E" + mantissa);
0404:                    }
0405:                } else if (mantissa <= -1) {
0406:                    digits.insert(0, "0.");
0407:                    for (int i = mantissa; i < -1; i++) {
0408:                        digits.insert(2, '0');
0409:                    }
0410:                } else if (mantissa + 1 == length) {
0411:                    if (length > 1 && digits.charAt(digits.length() - 1) == '0') {
0412:                        digits.append('.');
0413:                    }
0414:                } else if (mantissa < length) {
0415:                    digits.insert(mantissa + 1, '.');
0416:                } else {
0417:                    for (int i = length; i <= mantissa; i++) {
0418:                        digits.append('0');
0419:                    }
0420:                }
0421:                if (!sign) {
0422:                    digits.insert(0, '-');
0423:                }
0424:                return digits.toString();
0425:            }
0426:
0427:            /**
0428:             * Formats this number in scientific notation.
0429:             * <p>
0430:             * A string such as "NaN" or "Infinity" may be returned by this method.
0431:             *
0432:             * @return representation of this number in scientific notation.
0433:             *
0434:             * @since ostermillerutils 1.00.00
0435:             */
0436:            public String toScientificNotation() {
0437:                if (digits == null)
0438:                    return original;
0439:                StringBuffer digits = new StringBuffer(this .digits.toString());
0440:                int length = digits.length();
0441:                if (length > 1) {
0442:                    digits.insert(1, '.');
0443:                }
0444:                if (mantissa != 0) {
0445:                    digits.append("E" + mantissa);
0446:                }
0447:                if (!sign) {
0448:                    digits.insert(0, '-');
0449:                }
0450:                return digits.toString();
0451:            }
0452:
0453:            /**
0454:             * Parsing state:
0455:             * Initial state before anything read.
0456:             *
0457:             * @since ostermillerutils 1.00.00
0458:             */
0459:            private final static int INITIAL = 0;
0460:            /**
0461:             * Parsing state:
0462:             * State in which a possible sign and
0463:             * possible leading zeros have been read.
0464:             *
0465:             * @since ostermillerutils 1.00.00
0466:             */
0467:            private final static int LEADZEROS = 1;
0468:            /**
0469:             * Parsing state:
0470:             * State in which a possible sign and
0471:             * at least one non-zero digit
0472:             * has been read followed by some number of
0473:             * zeros.  The decimal place has no
0474:             * been encountered yet.
0475:             *
0476:             * @since ostermillerutils 1.00.00
0477:             */
0478:            private final static int MIDZEROS = 2;
0479:            /**
0480:             * Parsing state:
0481:             * State in which a possible sign and
0482:             * at least one non-zero digit
0483:             * has been read.  The decimal place has no
0484:             * been encountered yet.
0485:             *
0486:             * @since ostermillerutils 1.00.00
0487:             */
0488:            private final static int DIGITS = 3;
0489:            /**
0490:             * Parsing state:
0491:             * State in which only a possible sign,
0492:             * leading zeros, and a decimal point
0493:             * have been encountered.
0494:             *
0495:             * @since ostermillerutils 1.00.00
0496:             */
0497:            private final static int LEADZEROSDOT = 4;
0498:            /**
0499:             * Parsing state:
0500:             * State in which a possible sign,
0501:             * at least one nonzero digit and a
0502:             * decimal point have been encountered.
0503:             *
0504:             * @since ostermillerutils 1.00.00
0505:             */
0506:            private final static int DIGITSDOT = 5;
0507:            /**
0508:             * Parsing state:
0509:             * State in which the exponent symbol
0510:             * 'E' has been encountered.
0511:             *
0512:             * @since ostermillerutils 1.00.00
0513:             */
0514:            private final static int MANTISSA = 6;
0515:            /**
0516:             * Parsing state:
0517:             * State in which the exponent symbol
0518:             * 'E' has been encountered followed
0519:             * by a possible sign or some number
0520:             * of digits.
0521:             *
0522:             * @since ostermillerutils 1.00.00
0523:             */
0524:            private final static int MANTISSADIGIT = 7;
0525:
0526:            /**
0527:             * Parse a number from the given string.
0528:             * A valid number has an optional sign, some digits
0529:             * with an optional decimal point, and an optional
0530:             * scientific notation part consisting of an 'E' followed
0531:             * by an optional sign, followed by some digits.
0532:             *
0533:             * @param number String representation of a number.
0534:             * @throws NumberFormatException if the string is not a valid number.
0535:             *
0536:             * @since ostermillerutils 1.00.00
0537:             */
0538:            private void parse(String number) throws NumberFormatException {
0539:                int length = number.length();
0540:                digits = new StringBuffer(length);
0541:                int state = INITIAL;
0542:                int mantissaStart = -1;
0543:                boolean foundMantissaDigit = false;
0544:                // sometimes we don't know if a zero will be
0545:                // significant or not when it is encountered.
0546:                // keep track of the number of them so that
0547:                // the all can be made significant if we find
0548:                // out that they are.
0549:                int zeroCount = 0;
0550:                int leadZeroCount = 0;
0551:
0552:                for (int i = 0; i < length; i++) {
0553:                    char c = number.charAt(i);
0554:                    switch (c) {
0555:                    case '.': {
0556:                        switch (state) {
0557:                        case INITIAL:
0558:                        case LEADZEROS: {
0559:                            state = LEADZEROSDOT;
0560:                        }
0561:                            break;
0562:                        case MIDZEROS: {
0563:                            // we now know that these zeros
0564:                            // are more than just trailing place holders.
0565:                            for (int j = 0; j < zeroCount; j++) {
0566:                                digits.append('0');
0567:                            }
0568:                            zeroCount = 0;
0569:                            state = DIGITSDOT;
0570:                        }
0571:                            break;
0572:                        case DIGITS: {
0573:                            state = DIGITSDOT;
0574:                        }
0575:                            break;
0576:                        default: {
0577:                            throw new NumberFormatException(
0578:                                    "Unexpected character '" + c
0579:                                            + "' at position " + i);
0580:                        }
0581:                        }
0582:                    }
0583:                        break;
0584:                    case '+': {
0585:                        switch (state) {
0586:                        case INITIAL: {
0587:                            sign = true;
0588:                            state = LEADZEROS;
0589:                        }
0590:                            break;
0591:                        case MANTISSA: {
0592:                            state = MANTISSADIGIT;
0593:                        }
0594:                            break;
0595:                        default: {
0596:                            throw new NumberFormatException(
0597:                                    "Unexpected character '" + c
0598:                                            + "' at position " + i);
0599:                        }
0600:                        }
0601:                    }
0602:                        break;
0603:                    case '-': {
0604:                        switch (state) {
0605:                        case INITIAL: {
0606:                            sign = false;
0607:                            state = LEADZEROS;
0608:                        }
0609:                            break;
0610:                        case MANTISSA: {
0611:                            state = MANTISSADIGIT;
0612:                        }
0613:                            break;
0614:                        default: {
0615:                            throw new NumberFormatException(
0616:                                    "Unexpected character '" + c
0617:                                            + "' at position " + i);
0618:                        }
0619:                        }
0620:                    }
0621:                        break;
0622:                    case '0': {
0623:                        switch (state) {
0624:                        case INITIAL:
0625:                        case LEADZEROS: {
0626:                            // only significant if number
0627:                            // is all zeros.
0628:                            zeroCount++;
0629:                            leadZeroCount++;
0630:                            state = LEADZEROS;
0631:                        }
0632:                            break;
0633:                        case MIDZEROS:
0634:                        case DIGITS: {
0635:                            // only significant if followed
0636:                            // by a decimal point or nonzero digit.
0637:                            mantissa++;
0638:                            zeroCount++;
0639:                            state = MIDZEROS;
0640:                        }
0641:                            break;
0642:                        case LEADZEROSDOT: {
0643:                            // only significant if number
0644:                            // is all zeros.
0645:                            mantissa--;
0646:                            zeroCount++;
0647:                            state = LEADZEROSDOT;
0648:                        }
0649:                            break;
0650:                        case DIGITSDOT: {
0651:                            // non-leading zeros after
0652:                            // a decimal point are always
0653:                            // significant.
0654:                            digits.append(c);
0655:                        }
0656:                            break;
0657:                        case MANTISSA:
0658:                        case MANTISSADIGIT: {
0659:                            foundMantissaDigit = true;
0660:                            state = MANTISSADIGIT;
0661:                        }
0662:                            break;
0663:                        default: {
0664:                            throw new NumberFormatException(
0665:                                    "Unexpected character '" + c
0666:                                            + "' at position " + i);
0667:                        }
0668:                        }
0669:                    }
0670:                        break;
0671:                    case '1':
0672:                    case '2':
0673:                    case '3':
0674:                    case '4':
0675:                    case '5':
0676:                    case '6':
0677:                    case '7':
0678:                    case '8':
0679:                    case '9': {
0680:                        switch (state) {
0681:                        case INITIAL:
0682:                        case LEADZEROS:
0683:                        case DIGITS: {
0684:                            zeroCount = 0;
0685:                            digits.append(c);
0686:                            mantissa++;
0687:                            state = DIGITS;
0688:                        }
0689:                            break;
0690:                        case MIDZEROS: {
0691:                            // we now know that these zeros
0692:                            // are more than just trailing place holders.
0693:                            for (int j = 0; j < zeroCount; j++) {
0694:                                digits.append('0');
0695:                            }
0696:                            zeroCount = 0;
0697:                            digits.append(c);
0698:                            mantissa++;
0699:                            state = DIGITS;
0700:                        }
0701:                            break;
0702:                        case LEADZEROSDOT:
0703:                        case DIGITSDOT: {
0704:                            zeroCount = 0;
0705:                            digits.append(c);
0706:                            state = DIGITSDOT;
0707:                        }
0708:                            break;
0709:                        case MANTISSA:
0710:                        case MANTISSADIGIT: {
0711:                            state = MANTISSADIGIT;
0712:                            foundMantissaDigit = true;
0713:                        }
0714:                            break;
0715:                        default: {
0716:                            throw new NumberFormatException(
0717:                                    "Unexpected character '" + c
0718:                                            + "' at position " + i);
0719:                        }
0720:                        }
0721:                    }
0722:                        break;
0723:                    case 'E':
0724:                    case 'e': {
0725:                        switch (state) {
0726:                        case INITIAL:
0727:                        case LEADZEROS:
0728:                        case DIGITS:
0729:                        case LEADZEROSDOT:
0730:                        case DIGITSDOT: {
0731:                            // record the starting point of the mantissa
0732:                            // so we can do a substring to get it back later
0733:                            mantissaStart = i + 1;
0734:                            state = MANTISSA;
0735:                        }
0736:                            break;
0737:                        default: {
0738:                            throw new NumberFormatException(
0739:                                    "Unexpected character '" + c
0740:                                            + "' at position " + i);
0741:                        }
0742:                        }
0743:                    }
0744:                        break;
0745:                    default: {
0746:                        throw new NumberFormatException(
0747:                                "Unexpected character '" + c + "' at position "
0748:                                        + i);
0749:                    }
0750:                    }
0751:                }
0752:                if (mantissaStart != -1) {
0753:                    // if we had found an 'E'
0754:                    if (!foundMantissaDigit) {
0755:                        // we didn't actually find a mantissa to go with.
0756:                        throw new NumberFormatException(
0757:                                "No digits in mantissa.");
0758:                    }
0759:                    // parse the mantissa.
0760:                    mantissa += Integer.parseInt(number
0761:                            .substring(mantissaStart));
0762:                }
0763:                if (digits.length() == 0) {
0764:                    if (zeroCount > 0) {
0765:                        // if nothing but zeros all zeros are significant.
0766:                        for (int j = 0; j < zeroCount; j++) {
0767:                            digits.append('0');
0768:                        }
0769:                        mantissa += leadZeroCount;
0770:                        isZero = true;
0771:                        sign = true;
0772:                    } else {
0773:                        // a hack to catch some cases that we could catch
0774:                        // by adding a ton of extra states.  Things like:
0775:                        // "e2" "+e2" "+." "." "+" etc.
0776:                        throw new NumberFormatException("No digits in number.");
0777:                    }
0778:                }
0779:            }
0780:
0781:            /**
0782:             * Adjust the number of digits in the number.
0783:             * Pad the tail with zeros if too short, round the
0784:             * number according to scientific rounding if too long, leave alone
0785:             * if just right.
0786:             * <p>
0787:             * This method has no effect if this number is not a number or infinity.
0788:             *
0789:             * @param significantFigures desired number of significant figures.
0790:             * @return This number.
0791:             *
0792:             * @since ostermillerutils 1.00.00
0793:             */
0794:            public SignificantFigures setNumberSignificantFigures(
0795:                    int significantFigures) {
0796:                if (significantFigures <= 0)
0797:                    throw new IllegalArgumentException(
0798:                            "Desired number of significant figures must be positive.");
0799:                if (digits != null) {
0800:                    int length = digits.length();
0801:                    if (length < significantFigures) {
0802:                        // number is not long enough, pad it with zeros.
0803:                        for (int i = length; i < significantFigures; i++) {
0804:                            digits.append('0');
0805:                        }
0806:                    } else if (length > significantFigures) {
0807:                        // number is too long chop some of it off with rounding.
0808:                        boolean addOne; // we need to round up if true.
0809:                        char firstInSig = digits.charAt(significantFigures);
0810:                        if (firstInSig < '5') {
0811:                            // first non-significant digit less than five, round down.
0812:                            addOne = false;
0813:                        } else if (firstInSig == '5') {
0814:                            // first non-significant digit equal to five
0815:                            addOne = false;
0816:                            for (int i = significantFigures + 1; !addOne
0817:                                    && i < length; i++) {
0818:                                // if its followed by any non-zero digits, round up.
0819:                                if (digits.charAt(i) != '0') {
0820:                                    addOne = true;
0821:                                }
0822:                            }
0823:                            if (!addOne) {
0824:                                // if it was not followed by non-zero digits
0825:                                // if the last significant digit is odd round up
0826:                                // if the last significant digit is even round down
0827:                                addOne = (digits.charAt(significantFigures - 1) & 1) == 1;
0828:                            }
0829:                        } else {
0830:                            // first non-significant digit greater than five, round up.
0831:                            addOne = true;
0832:                        }
0833:                        // loop to add one (and carry a one if added to a nine)
0834:                        // to the last significant digit
0835:                        for (int i = significantFigures - 1; addOne && i >= 0; i--) {
0836:                            char digit = digits.charAt(i);
0837:                            if (digit < '9') {
0838:                                digits.setCharAt(i, (char) (digit + 1));
0839:                                addOne = false;
0840:                            } else {
0841:                                digits.setCharAt(i, '0');
0842:                            }
0843:                        }
0844:                        if (addOne) {
0845:                            // if the number was all nines
0846:                            digits.insert(0, '1');
0847:                            mantissa++;
0848:                        }
0849:                        // chop it to the correct number of figures.
0850:                        digits.setLength(significantFigures);
0851:                    }
0852:                }
0853:                return this ;
0854:            }
0855:
0856:            /**
0857:             * Returns the value of this number as a byte.
0858:             *
0859:             * @return the numeric value represented by this object after conversion to type byte.
0860:             * @throws NumberFormatException if this number cannot be converted to a byte.
0861:             *
0862:             * @since ostermillerutils 1.00.00
0863:             */
0864:            @Override
0865:            public byte byteValue() throws NumberFormatException {
0866:                return Byte.parseByte(original);
0867:            }
0868:
0869:            /**
0870:             * Returns the value of this number as a double.
0871:             *
0872:             * @return the numeric value represented by this object after conversion to type double.
0873:             * @throws NumberFormatException if this number cannot be converted to a double.
0874:             *
0875:             * @since ostermillerutils 1.00.00
0876:             */
0877:            @Override
0878:            public double doubleValue() throws NumberFormatException {
0879:                return Double.parseDouble(original);
0880:            }
0881:
0882:            /**
0883:             * Returns the value of this number as a float.
0884:             *
0885:             * @return the numeric value represented by this object after conversion to type float.
0886:             * @throws NumberFormatException if this number cannot be converted to a float.
0887:             *
0888:             * @since ostermillerutils 1.00.00
0889:             */
0890:            @Override
0891:            public float floatValue() throws NumberFormatException {
0892:                return Float.parseFloat(original);
0893:            }
0894:
0895:            /**
0896:             * Returns the value of this number as a int.
0897:             *
0898:             * @return the numeric value represented by this object after conversion to type int.
0899:             * @throws NumberFormatException if this number cannot be converted to a int.
0900:             *
0901:             * @since ostermillerutils 1.00.00
0902:             */
0903:            @Override
0904:            public int intValue() throws NumberFormatException {
0905:                return Integer.parseInt(original);
0906:            }
0907:
0908:            /**
0909:             * Returns the value of this number as a long.
0910:             *
0911:             * @return the numeric value represented by this object after conversion to type long.
0912:             * @throws NumberFormatException if this number cannot be converted to a long.
0913:             *
0914:             * @since ostermillerutils 1.00.00
0915:             */
0916:            @Override
0917:            public long longValue() throws NumberFormatException {
0918:                return Long.parseLong(original);
0919:            }
0920:
0921:            /**
0922:             * Returns the value of this number as a short.
0923:             *
0924:             * @return the numeric value represented by this object after conversion to type short.
0925:             * @throws NumberFormatException if this number cannot be converted to a short.
0926:             *
0927:             * @since ostermillerutils 1.00.00
0928:             */
0929:            @Override
0930:            public short shortValue() throws NumberFormatException {
0931:                return Short.parseShort(original);
0932:            }
0933:
0934:            /**
0935:             * Convenience method to display a number with the correct
0936:             * significant digits.
0937:             *
0938:             * @param number the number to display
0939:             * @param significantFigures the number of significant figures to display.
0940:             * @return the number formatted with the correct significant figures
0941:             *
0942:             * @since ostermillerutils 1.02.07
0943:             */
0944:            public static String format(byte number, int significantFigures) {
0945:                SignificantFigures sf = new SignificantFigures(number);
0946:                sf.setNumberSignificantFigures(significantFigures);
0947:                return sf.toString();
0948:            }
0949:
0950:            /**
0951:             * Convenience method to display a number with the correct
0952:             * significant digits.
0953:             *
0954:             * @param number the number to display
0955:             * @param significantFigures the number of significant figures to display.
0956:             * @return the number formatted with the correct significant figures
0957:             *
0958:             * @since ostermillerutils 1.02.07
0959:             */
0960:            public static String format(double number, int significantFigures) {
0961:                SignificantFigures sf = new SignificantFigures(number);
0962:                sf.setNumberSignificantFigures(significantFigures);
0963:                return sf.toString();
0964:            }
0965:
0966:            /**
0967:             * Convenience method to display a number with the correct
0968:             * significant digits.
0969:             *
0970:             * @param number the number to display
0971:             * @param significantFigures the number of significant figures to display.
0972:             * @return the number formatted with the correct significant figures
0973:             *
0974:             * @since ostermillerutils 1.02.07
0975:             */
0976:            public static String format(float number, int significantFigures) {
0977:                SignificantFigures sf = new SignificantFigures(number);
0978:                sf.setNumberSignificantFigures(significantFigures);
0979:                return sf.toString();
0980:            }
0981:
0982:            /**
0983:             * Convenience method to display a number with the correct
0984:             * significant digits.
0985:             *
0986:             * @param number the number to display
0987:             * @param significantFigures the number of significant figures to display.
0988:             * @return the number formatted with the correct significant figures
0989:             *
0990:             * @since ostermillerutils 1.02.07
0991:             */
0992:            public static String format(int number, int significantFigures) {
0993:                SignificantFigures sf = new SignificantFigures(number);
0994:                sf.setNumberSignificantFigures(significantFigures);
0995:                return sf.toString();
0996:            }
0997:
0998:            /**
0999:             * Convenience method to display a number with the correct
1000:             * significant digits.
1001:             *
1002:             * @param number the number to display
1003:             * @param significantFigures the number of significant figures to display.
1004:             * @return the number formatted with the correct significant figures
1005:             *
1006:             * @since ostermillerutils 1.02.07
1007:             */
1008:            public static String format(long number, int significantFigures) {
1009:                SignificantFigures sf = new SignificantFigures(number);
1010:                sf.setNumberSignificantFigures(significantFigures);
1011:                return sf.toString();
1012:            }
1013:
1014:            /**
1015:             * Convenience method to display a number with the correct
1016:             * significant digits.
1017:             *
1018:             * @param number the number to display
1019:             * @param significantFigures the number of significant figures to display.
1020:             * @return the number formatted with the correct significant figures
1021:             *
1022:             * @since ostermillerutils 1.02.07
1023:             */
1024:            public static String format(Number number, int significantFigures) {
1025:                SignificantFigures sf = new SignificantFigures(number);
1026:                sf.setNumberSignificantFigures(significantFigures);
1027:                return sf.toString();
1028:            }
1029:
1030:            /**
1031:             * Convenience method to display a number with the correct
1032:             * significant digits.
1033:             *
1034:             * @param number the number to display
1035:             * @param significantFigures the number of significant figures to display.
1036:             * @return the number formatted with the correct significant figures
1037:             *
1038:             * @since ostermillerutils 1.02.07
1039:             */
1040:            public static String format(short number, int significantFigures) {
1041:                SignificantFigures sf = new SignificantFigures(number);
1042:                sf.setNumberSignificantFigures(significantFigures);
1043:                return sf.toString();
1044:            }
1045:
1046:            /**
1047:             * Convenience method to display a number with the correct
1048:             * significant digits.
1049:             *
1050:             * @param number the number to display
1051:             * @param significantFigures the number of significant figures to display.
1052:             * @return the number formatted with the correct significant figures
1053:             * @throws NumberFormatException if the String is not a valid number.
1054:             *
1055:             * @since ostermillerutils 1.02.07
1056:             */
1057:            public static String format(String number, int significantFigures)
1058:                    throws NumberFormatException {
1059:                SignificantFigures sf = new SignificantFigures(number);
1060:                sf.setNumberSignificantFigures(significantFigures);
1061:                return sf.toString();
1062:            }
1063:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.