SignificantFigures.java Source code

Java tutorial

Introduction

Here is the source code for SignificantFigures.java

Source

/*
 * Copyright (C) 2002-2007 Stephen Ostermiller
 * http://ostermiller.org/contact.pl?regarding=Java+Utilities
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * See COPYING.TXT for details.
 */

/**
 * A number with an associated number of significant figures.
 * This class handles parsing numbers, determining the number
 * of significant figures, adjusting the number of significant
 * figures (including scientific rounding), and displaying the number.
 * More information about this class is available from <a target="_top" href=
 * "http://ostermiller.org/utils/SignificantFigures.html">ostermiller.org</a>.
 * <p>
 * When parsing a number to determine the number of significant figures,
 * these rules are used:
 * <ul>
 * <li>Non-zero digits are always significant.</li>
 * <li>All zeros between other significant digits are significant.</li>
 * <li>All zeros left of the decimal point between a significant digit and the decimal point are significant.</li>
 * <li>All trailing zeros to the right of the decimal point are significant.</li>
 * <li>If the number is contains no digits other than zero, every zero is significant.</li>
 * </ul>
 * <p>
 * When rounding a number the following rules are used:
 * <ul>
 * <li>If the greatest insignificant digit is less than five, round down.</li>
 * <li>If the greatest insignificant digit is greater than five, round up.</li>
 * <li>If the greatest insignificant digit is five and followed by some non-zero digit, round up.</li>
 * <li>If the greatest insignificant digit is five and followed only by zeros, and the least significant
 * digit is odd, round up.</li>
 * <li>If the greatest insignificant digit is five and followed only by zeros, and the least significant
 * digit is even, round down.</li>
 * </ul>
 *
 * <p>
 * Example of using this class to multiply numbers and display the result
 * with the proper number of significant figures:<br>
 * <pre> String[] arguments = {"1.0", "2.0", ...}
 * SignificantFigures number;
 * int sigFigs = Integer.MAX_VALUE;
 * double result = 1D;
 * for (int i=0; i&lt;arguments.length; i++){
 * &nbsp;   number = new SignificantFigures(arguments[i]);
 * &nbsp;   sigFigs = Math.min(sigFigs, number.getNumberSignificantFigures());
 * &nbsp;   result *= number.doubleValue();
 * }
 * number = new SignificantFigures(result);
 * number.setNumberSignificantFigures(sigFigs);
 * System.out.println(number);</pre>
 * <p>
 * Example of using this class to add numbers and display the result
 * with the proper number of significant figures:<br>
 * <pre> String[] arguments = {"1.0", "2.0", ...}
 * SignificantFigures number;
 * int leastSD = Integer.MIN_VALUE;
 * int mostSD = Integer.MIN_VALUE;
 * double result = 0D;
 * for (int i=0; i&lt;arguments.length; i++){
 * &nbsp;   number = new SignificantFigures(arguments[i]);
 * &nbsp;   leastSD = Math.max(leastSD, number.getLSD());
 * &nbsp;   mostSD = Math.max(mostSD, number.getMSD());
 * &nbsp;   result += number.doubleValue();
 * }
 * number = new SignificantFigures(result);
 * number.setLMSD(leastSD, mostSD);
 * System.out.println(number);</pre>
 *
 * @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities
 * @since ostermillerutils 1.00.00
 */
public class SignificantFigures extends Number {

    /**
     *
     */
    private static final long serialVersionUID = -1130798283937219608L;
    /**
     * In the case the a number
     * could not be parsed, the original is stored
     * for toString purposes.
     *
     * @since ostermillerutils 1.00.00
     */
    private String original;
    /**
     * Buffer of the significant digits.
     *
     * @since ostermillerutils 1.00.00
     */
    private StringBuffer digits;
    /**
     * The exponent of the digits if a
     * decimal place were inserted after
     * the first digit.
     *
     * @since ostermillerutils 1.00.00
     */
    private int mantissa = -1;
    /**
     * positive if true, negative if false.
     *
     * @since ostermillerutils 1.00.00
     */
    private boolean sign = true;
    /**
     * True if this number has no non-zero digits.
     *
     * @since ostermillerutils 1.00.00
     */
    private boolean isZero = false;

    /**
     * Create a SignificantFigures object from a String representation of a number.
     *
     * @param number String representation of the number.
     * @throws NumberFormatException if the String is not a valid number.
     *
     * @since ostermillerutils 1.00.00
     */
    public SignificantFigures(String number) throws NumberFormatException {
        original = number;
        parse(original);
    }

    /**
     * Create a SignificantFigures object from a byte.
     *
     * @param number an 8 bit integer.
     *
     * @since ostermillerutils 1.00.00
     */
    public SignificantFigures(byte number) {
        original = Byte.toString(number);
        try {
            parse(original);
        } catch (NumberFormatException nfe) {
            digits = null;
        }
    }

    /**
     * Create a SignificantFigures object from a short.
     *
     * @param number a 16 bit integer.
     *
     * @since ostermillerutils 1.00.00
     */
    public SignificantFigures(short number) {
        original = Short.toString(number);
        try {
            parse(original);
        } catch (NumberFormatException nfe) {
            digits = null;
        }
    }

    /**
     * Create a SignificantFigures object from an integer.
     *
     * @param number a 32 bit integer.
     *
     * @since ostermillerutils 1.00.00
     */
    public SignificantFigures(int number) {
        original = String.valueOf(number);
        try {
            parse(original);
        } catch (NumberFormatException nfe) {
            digits = null;
        }
    }

    /**
     * Create a SignificantFigures object from a long.
     *
     * @param number a 64 bit integer.
     *
     * @since ostermillerutils 1.00.00
     */
    public SignificantFigures(long number) {
        original = Long.toString(number);
        try {
            parse(original);
        } catch (NumberFormatException nfe) {
            digits = null;
        }
    }

    /**
     * Create a SignificantFigures object from a float.
     *
     * @param number a 32 bit floating point.
     *
     * @since ostermillerutils 1.00.00
     */
    public SignificantFigures(float number) {
        original = Float.toString(number);
        try {
            parse(original);
        } catch (NumberFormatException nfe) {
            digits = null;
        }
    }

    /**
     * Create a SignificantFigures object from a double.
     *
     * @param number a 64 bit floating point.
     *
     * @since ostermillerutils 1.00.00
     */
    public SignificantFigures(double number) {
        original = Double.toString(number);
        try {
            parse(original);
        } catch (NumberFormatException nfe) {
            digits = null;
        }
    }

    /**
     * Create a SignificantFigures object from a java number such as
     * a BigDecimal, BigInteger, Byte, Double, Float, Integer, Long, or
     * Short.
     *
     * @param number a number.
     *
     * @since ostermillerutils 1.00.00
     */
    public SignificantFigures(Number number) {
        original = number.toString();
        try {
            parse(original);
        } catch (NumberFormatException nfe) {
            digits = null;
        }
    }

    /**
     * Get the number of significant digits.
     * <p>
     * If this number is not a number or infinity zero
     * will be returned.
     *
     * @return the number of significant digits in this number.
     *
     * @since ostermillerutils 1.00.00
     */
    public int getNumberSignificantFigures() {
        if (digits == null)
            return 0;
        return digits.length();
    }

    /**
     * Adjust the number of significant figures such that the least
     * significant digit is at the given place.  This method may add
     * significant zeros to the end of this number, or remove significant
     * digits from this number.
     * <p>
     * It is possible to remove all significant digits from this number which
     * will cause the string representation of this number to become "NaN".  This
     * could become a problem if you are adding numbers and the result is close
     * to zero.  All of the significant digits may get removed, even though the
     * result could be zero with some number of significant digits.  Its is safes
     * to use the setLMSD() method which will make a zero with the appropriate
     * number of significant figures in such instances.
     * <p>
     * This method has no effect if this number is not a number or infinity.
     *
     * @param place the desired place of the least significant digit.
     * @return this number.
     *
     * @since ostermillerutils 1.00.00
     */
    public SignificantFigures setLSD(int place) {
        setLMSD(place, Integer.MIN_VALUE);
        return this;
    }

    /**
     * Adjust the number of significant figures such that the least
     * significant digit is at the given place.  This method may add
     * significant zeros to the end of this number, or remove significant
     * digits from this number.
     * <p>
     * If all significant digits are removed from this number by truncating to
     * the least significant place, a zero will be created with significant figures
     * from the least to most significant places.
     * <p>
     * This method has no effect if this number is not a number or infinity.
     *
     * @param leastPlace the desired place of the least significant digit or Integer.MIN_VALUE to ignore.
     * @param mostPlace the desired place of the most significant digit or Integer.MIN_VALUE to ignore.
     * @return this number
     *
     * @since ostermillerutils 1.00.00
     */
    public SignificantFigures setLMSD(int leastPlace, int mostPlace) {
        if (digits != null && leastPlace != Integer.MIN_VALUE) {
            int significantFigures = digits.length();
            int current = mantissa - significantFigures + 1;
            int newLength = significantFigures - leastPlace + current;
            if (newLength <= 0) {
                if (mostPlace == Integer.MIN_VALUE) {
                    original = "NaN";
                    digits = null;
                } else {
                    newLength = mostPlace - leastPlace + 1;
                    digits.setLength(newLength);
                    mantissa = leastPlace;
                    for (int i = 0; i < newLength; i++) {
                        digits.setCharAt(i, '0');
                    }
                    isZero = true;
                    sign = true;
                }
            } else {
                digits.setLength(newLength);
                for (int i = significantFigures; i < newLength; i++) {
                    digits.setCharAt(i, '0');
                }
            }
        }
        return this;
    }

    /**
     * Get the decimal place of the least significant digit.
     * <p>
     * If this number is not a number or infinity Integer.MIN_VALUE
     * will be returned.
     *
     * @return the decimal place of the least significant digit.
     *
     * @since ostermillerutils 1.00.00
     */
    public int getLSD() {
        if (digits == null)
            return Integer.MIN_VALUE;
        return mantissa - digits.length() + 1;
    }

    /**
     * Get the decimal place of the most significant digit.
     * <p>
     * If this number is not a number or infinity Integer.MIN_VALUE
     * will be returned.
     *
     * @return the decimal place of the least significant digit.
     *
     * @since ostermillerutils 1.00.00
     */
    public int getMSD() {
        if (digits == null)
            return Integer.MIN_VALUE;
        return mantissa + 1;
    }

    /**
     * Formats this number.
     * If the number is less than 10^-3 or greater than or equal to 10^7,
     * or the number might have an ambiguous number of significant figures,
     * scientific notation will be used.
     * <p>
     * A string such as "NaN" or "Infinity" may be returned by this method.
     *
     * @return representation of this number.
     *
     * @since ostermillerutils 1.00.00
     */
    @Override
    public String toString() {
        if (digits == null)
            return original;
        StringBuffer digits = new StringBuffer(this.digits.toString());
        int length = digits.length();
        if (mantissa <= -4 || mantissa >= 7 || (mantissa >= length && digits.charAt(digits.length() - 1) == '0')
                || (isZero && mantissa != 0)) {
            // use scientific notation.
            if (length > 1) {
                digits.insert(1, '.');
            }
            if (mantissa != 0) {
                digits.append("E" + mantissa);
            }
        } else if (mantissa <= -1) {
            digits.insert(0, "0.");
            for (int i = mantissa; i < -1; i++) {
                digits.insert(2, '0');
            }
        } else if (mantissa + 1 == length) {
            if (length > 1 && digits.charAt(digits.length() - 1) == '0') {
                digits.append('.');
            }
        } else if (mantissa < length) {
            digits.insert(mantissa + 1, '.');
        } else {
            for (int i = length; i <= mantissa; i++) {
                digits.append('0');
            }
        }
        if (!sign) {
            digits.insert(0, '-');
        }
        return digits.toString();
    }

    /**
     * Formats this number in scientific notation.
     * <p>
     * A string such as "NaN" or "Infinity" may be returned by this method.
     *
     * @return representation of this number in scientific notation.
     *
     * @since ostermillerutils 1.00.00
     */
    public String toScientificNotation() {
        if (digits == null)
            return original;
        StringBuffer digits = new StringBuffer(this.digits.toString());
        int length = digits.length();
        if (length > 1) {
            digits.insert(1, '.');
        }
        if (mantissa != 0) {
            digits.append("E" + mantissa);
        }
        if (!sign) {
            digits.insert(0, '-');
        }
        return digits.toString();
    }

    /**
     * Parsing state:
     * Initial state before anything read.
     *
     * @since ostermillerutils 1.00.00
     */
    private final static int INITIAL = 0;
    /**
     * Parsing state:
     * State in which a possible sign and
     * possible leading zeros have been read.
     *
     * @since ostermillerutils 1.00.00
     */
    private final static int LEADZEROS = 1;
    /**
     * Parsing state:
     * State in which a possible sign and
     * at least one non-zero digit
     * has been read followed by some number of
     * zeros.  The decimal place has no
     * been encountered yet.
     *
     * @since ostermillerutils 1.00.00
     */
    private final static int MIDZEROS = 2;
    /**
     * Parsing state:
     * State in which a possible sign and
     * at least one non-zero digit
     * has been read.  The decimal place has no
     * been encountered yet.
     *
     * @since ostermillerutils 1.00.00
     */
    private final static int DIGITS = 3;
    /**
     * Parsing state:
     * State in which only a possible sign,
     * leading zeros, and a decimal point
     * have been encountered.
     *
     * @since ostermillerutils 1.00.00
     */
    private final static int LEADZEROSDOT = 4;
    /**
     * Parsing state:
     * State in which a possible sign,
     * at least one nonzero digit and a
     * decimal point have been encountered.
     *
     * @since ostermillerutils 1.00.00
     */
    private final static int DIGITSDOT = 5;
    /**
     * Parsing state:
     * State in which the exponent symbol
     * 'E' has been encountered.
     *
     * @since ostermillerutils 1.00.00
     */
    private final static int MANTISSA = 6;
    /**
     * Parsing state:
     * State in which the exponent symbol
     * 'E' has been encountered followed
     * by a possible sign or some number
     * of digits.
     *
     * @since ostermillerutils 1.00.00
     */
    private final static int MANTISSADIGIT = 7;

    /**
     * Parse a number from the given string.
     * A valid number has an optional sign, some digits
     * with an optional decimal point, and an optional
     * scientific notation part consisting of an 'E' followed
     * by an optional sign, followed by some digits.
     *
     * @param number String representation of a number.
     * @throws NumberFormatException if the string is not a valid number.
     *
     * @since ostermillerutils 1.00.00
     */
    private void parse(String number) throws NumberFormatException {
        int length = number.length();
        digits = new StringBuffer(length);
        int state = INITIAL;
        int mantissaStart = -1;
        boolean foundMantissaDigit = false;
        // sometimes we don't know if a zero will be
        // significant or not when it is encountered.
        // keep track of the number of them so that
        // the all can be made significant if we find
        // out that they are.
        int zeroCount = 0;
        int leadZeroCount = 0;

        for (int i = 0; i < length; i++) {
            char c = number.charAt(i);
            switch (c) {
            case '.': {
                switch (state) {
                case INITIAL:
                case LEADZEROS: {
                    state = LEADZEROSDOT;
                }
                    break;
                case MIDZEROS: {
                    // we now know that these zeros
                    // are more than just trailing place holders.
                    for (int j = 0; j < zeroCount; j++) {
                        digits.append('0');
                    }
                    zeroCount = 0;
                    state = DIGITSDOT;
                }
                    break;
                case DIGITS: {
                    state = DIGITSDOT;
                }
                    break;
                default: {
                    throw new NumberFormatException("Unexpected character '" + c + "' at position " + i);
                }
                }
            }
                break;
            case '+': {
                switch (state) {
                case INITIAL: {
                    sign = true;
                    state = LEADZEROS;
                }
                    break;
                case MANTISSA: {
                    state = MANTISSADIGIT;
                }
                    break;
                default: {
                    throw new NumberFormatException("Unexpected character '" + c + "' at position " + i);
                }
                }
            }
                break;
            case '-': {
                switch (state) {
                case INITIAL: {
                    sign = false;
                    state = LEADZEROS;
                }
                    break;
                case MANTISSA: {
                    state = MANTISSADIGIT;
                }
                    break;
                default: {
                    throw new NumberFormatException("Unexpected character '" + c + "' at position " + i);
                }
                }
            }
                break;
            case '0': {
                switch (state) {
                case INITIAL:
                case LEADZEROS: {
                    // only significant if number
                    // is all zeros.
                    zeroCount++;
                    leadZeroCount++;
                    state = LEADZEROS;
                }
                    break;
                case MIDZEROS:
                case DIGITS: {
                    // only significant if followed
                    // by a decimal point or nonzero digit.
                    mantissa++;
                    zeroCount++;
                    state = MIDZEROS;
                }
                    break;
                case LEADZEROSDOT: {
                    // only significant if number
                    // is all zeros.
                    mantissa--;
                    zeroCount++;
                    state = LEADZEROSDOT;
                }
                    break;
                case DIGITSDOT: {
                    // non-leading zeros after
                    // a decimal point are always
                    // significant.
                    digits.append(c);
                }
                    break;
                case MANTISSA:
                case MANTISSADIGIT: {
                    foundMantissaDigit = true;
                    state = MANTISSADIGIT;
                }
                    break;
                default: {
                    throw new NumberFormatException("Unexpected character '" + c + "' at position " + i);
                }
                }
            }
                break;
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9': {
                switch (state) {
                case INITIAL:
                case LEADZEROS:
                case DIGITS: {
                    zeroCount = 0;
                    digits.append(c);
                    mantissa++;
                    state = DIGITS;
                }
                    break;
                case MIDZEROS: {
                    // we now know that these zeros
                    // are more than just trailing place holders.
                    for (int j = 0; j < zeroCount; j++) {
                        digits.append('0');
                    }
                    zeroCount = 0;
                    digits.append(c);
                    mantissa++;
                    state = DIGITS;
                }
                    break;
                case LEADZEROSDOT:
                case DIGITSDOT: {
                    zeroCount = 0;
                    digits.append(c);
                    state = DIGITSDOT;
                }
                    break;
                case MANTISSA:
                case MANTISSADIGIT: {
                    state = MANTISSADIGIT;
                    foundMantissaDigit = true;
                }
                    break;
                default: {
                    throw new NumberFormatException("Unexpected character '" + c + "' at position " + i);
                }
                }
            }
                break;
            case 'E':
            case 'e': {
                switch (state) {
                case INITIAL:
                case LEADZEROS:
                case DIGITS:
                case LEADZEROSDOT:
                case DIGITSDOT: {
                    // record the starting point of the mantissa
                    // so we can do a substring to get it back later
                    mantissaStart = i + 1;
                    state = MANTISSA;
                }
                    break;
                default: {
                    throw new NumberFormatException("Unexpected character '" + c + "' at position " + i);
                }
                }
            }
                break;
            default: {
                throw new NumberFormatException("Unexpected character '" + c + "' at position " + i);
            }
            }
        }
        if (mantissaStart != -1) {
            // if we had found an 'E'
            if (!foundMantissaDigit) {
                // we didn't actually find a mantissa to go with.
                throw new NumberFormatException("No digits in mantissa.");
            }
            // parse the mantissa.
            mantissa += Integer.parseInt(number.substring(mantissaStart));
        }
        if (digits.length() == 0) {
            if (zeroCount > 0) {
                // if nothing but zeros all zeros are significant.
                for (int j = 0; j < zeroCount; j++) {
                    digits.append('0');
                }
                mantissa += leadZeroCount;
                isZero = true;
                sign = true;
            } else {
                // a hack to catch some cases that we could catch
                // by adding a ton of extra states.  Things like:
                // "e2" "+e2" "+." "." "+" etc.
                throw new NumberFormatException("No digits in number.");
            }
        }
    }

    /**
     * Adjust the number of digits in the number.
     * Pad the tail with zeros if too short, round the
     * number according to scientific rounding if too long, leave alone
     * if just right.
     * <p>
     * This method has no effect if this number is not a number or infinity.
     *
     * @param significantFigures desired number of significant figures.
     * @return This number.
     *
     * @since ostermillerutils 1.00.00
     */
    public SignificantFigures setNumberSignificantFigures(int significantFigures) {
        if (significantFigures <= 0)
            throw new IllegalArgumentException("Desired number of significant figures must be positive.");
        if (digits != null) {
            int length = digits.length();
            if (length < significantFigures) {
                // number is not long enough, pad it with zeros.
                for (int i = length; i < significantFigures; i++) {
                    digits.append('0');
                }
            } else if (length > significantFigures) {
                // number is too long chop some of it off with rounding.
                boolean addOne; // we need to round up if true.
                char firstInSig = digits.charAt(significantFigures);
                if (firstInSig < '5') {
                    // first non-significant digit less than five, round down.
                    addOne = false;
                } else if (firstInSig == '5') {
                    // first non-significant digit equal to five
                    addOne = false;
                    for (int i = significantFigures + 1; !addOne && i < length; i++) {
                        // if its followed by any non-zero digits, round up.
                        if (digits.charAt(i) != '0') {
                            addOne = true;
                        }
                    }
                    if (!addOne) {
                        // if it was not followed by non-zero digits
                        // if the last significant digit is odd round up
                        // if the last significant digit is even round down
                        addOne = (digits.charAt(significantFigures - 1) & 1) == 1;
                    }
                } else {
                    // first non-significant digit greater than five, round up.
                    addOne = true;
                }
                // loop to add one (and carry a one if added to a nine)
                // to the last significant digit
                for (int i = significantFigures - 1; addOne && i >= 0; i--) {
                    char digit = digits.charAt(i);
                    if (digit < '9') {
                        digits.setCharAt(i, (char) (digit + 1));
                        addOne = false;
                    } else {
                        digits.setCharAt(i, '0');
                    }
                }
                if (addOne) {
                    // if the number was all nines
                    digits.insert(0, '1');
                    mantissa++;
                }
                // chop it to the correct number of figures.
                digits.setLength(significantFigures);
            }
        }
        return this;
    }

    /**
     * Returns the value of this number as a byte.
     *
     * @return the numeric value represented by this object after conversion to type byte.
     * @throws NumberFormatException if this number cannot be converted to a byte.
     *
     * @since ostermillerutils 1.00.00
     */
    @Override
    public byte byteValue() throws NumberFormatException {
        return Byte.parseByte(original);
    }

    /**
     * Returns the value of this number as a double.
     *
     * @return the numeric value represented by this object after conversion to type double.
     * @throws NumberFormatException if this number cannot be converted to a double.
     *
     * @since ostermillerutils 1.00.00
     */
    @Override
    public double doubleValue() throws NumberFormatException {
        return Double.parseDouble(original);
    }

    /**
     * Returns the value of this number as a float.
     *
     * @return the numeric value represented by this object after conversion to type float.
     * @throws NumberFormatException if this number cannot be converted to a float.
     *
     * @since ostermillerutils 1.00.00
     */
    @Override
    public float floatValue() throws NumberFormatException {
        return Float.parseFloat(original);
    }

    /**
     * Returns the value of this number as a int.
     *
     * @return the numeric value represented by this object after conversion to type int.
     * @throws NumberFormatException if this number cannot be converted to a int.
     *
     * @since ostermillerutils 1.00.00
     */
    @Override
    public int intValue() throws NumberFormatException {
        return Integer.parseInt(original);
    }

    /**
     * Returns the value of this number as a long.
     *
     * @return the numeric value represented by this object after conversion to type long.
     * @throws NumberFormatException if this number cannot be converted to a long.
     *
     * @since ostermillerutils 1.00.00
     */
    @Override
    public long longValue() throws NumberFormatException {
        return Long.parseLong(original);
    }

    /**
     * Returns the value of this number as a short.
     *
     * @return the numeric value represented by this object after conversion to type short.
     * @throws NumberFormatException if this number cannot be converted to a short.
     *
     * @since ostermillerutils 1.00.00
     */
    @Override
    public short shortValue() throws NumberFormatException {
        return Short.parseShort(original);
    }

    /**
     * Convenience method to display a number with the correct
     * significant digits.
     *
     * @param number the number to display
     * @param significantFigures the number of significant figures to display.
     * @return the number formatted with the correct significant figures
     *
     * @since ostermillerutils 1.02.07
     */
    public static String format(byte number, int significantFigures) {
        SignificantFigures sf = new SignificantFigures(number);
        sf.setNumberSignificantFigures(significantFigures);
        return sf.toString();
    }

    /**
     * Convenience method to display a number with the correct
     * significant digits.
     *
     * @param number the number to display
     * @param significantFigures the number of significant figures to display.
     * @return the number formatted with the correct significant figures
     *
     * @since ostermillerutils 1.02.07
     */
    public static String format(double number, int significantFigures) {
        SignificantFigures sf = new SignificantFigures(number);
        sf.setNumberSignificantFigures(significantFigures);
        return sf.toString();
    }

    /**
     * Convenience method to display a number with the correct
     * significant digits.
     *
     * @param number the number to display
     * @param significantFigures the number of significant figures to display.
     * @return the number formatted with the correct significant figures
     *
     * @since ostermillerutils 1.02.07
     */
    public static String format(float number, int significantFigures) {
        SignificantFigures sf = new SignificantFigures(number);
        sf.setNumberSignificantFigures(significantFigures);
        return sf.toString();
    }

    /**
     * Convenience method to display a number with the correct
     * significant digits.
     *
     * @param number the number to display
     * @param significantFigures the number of significant figures to display.
     * @return the number formatted with the correct significant figures
     *
     * @since ostermillerutils 1.02.07
     */
    public static String format(int number, int significantFigures) {
        SignificantFigures sf = new SignificantFigures(number);
        sf.setNumberSignificantFigures(significantFigures);
        return sf.toString();
    }

    /**
     * Convenience method to display a number with the correct
     * significant digits.
     *
     * @param number the number to display
     * @param significantFigures the number of significant figures to display.
     * @return the number formatted with the correct significant figures
     *
     * @since ostermillerutils 1.02.07
     */
    public static String format(long number, int significantFigures) {
        SignificantFigures sf = new SignificantFigures(number);
        sf.setNumberSignificantFigures(significantFigures);
        return sf.toString();
    }

    /**
     * Convenience method to display a number with the correct
     * significant digits.
     *
     * @param number the number to display
     * @param significantFigures the number of significant figures to display.
     * @return the number formatted with the correct significant figures
     *
     * @since ostermillerutils 1.02.07
     */
    public static String format(Number number, int significantFigures) {
        SignificantFigures sf = new SignificantFigures(number);
        sf.setNumberSignificantFigures(significantFigures);
        return sf.toString();
    }

    /**
     * Convenience method to display a number with the correct
     * significant digits.
     *
     * @param number the number to display
     * @param significantFigures the number of significant figures to display.
     * @return the number formatted with the correct significant figures
     *
     * @since ostermillerutils 1.02.07
     */
    public static String format(short number, int significantFigures) {
        SignificantFigures sf = new SignificantFigures(number);
        sf.setNumberSignificantFigures(significantFigures);
        return sf.toString();
    }

    /**
     * Convenience method to display a number with the correct
     * significant digits.
     *
     * @param number the number to display
     * @param significantFigures the number of significant figures to display.
     * @return the number formatted with the correct significant figures
     * @throws NumberFormatException if the String is not a valid number.
     *
     * @since ostermillerutils 1.02.07
     */
    public static String format(String number, int significantFigures) throws NumberFormatException {
        SignificantFigures sf = new SignificantFigures(number);
        sf.setNumberSignificantFigures(significantFigures);
        return sf.toString();
    }
}