/*
 * J.A.D.E. Java(TM) Addition to Default Environment.
 * Latest release available at http://jade.dautelle.com/
 * This class is public domain (not copyrighted).
 */
package org.codehaus.plexus.util;

This class provides utility methods to parse CharSequence into primitive types and to format primitive types into StringBuffer.

Methods from this utility class do not create temporary objects and are typically faster than standard library methods (e.g parseDouble is up to 15x faster than Double.parseDouble).

For class instances, formatting is typically performed using specialized java.text.Format (Locale sensitive) and/or using conventional methods (class sensitive). For example:
    public class Foo {
        public static Foo valueOf(CharSequence chars) {...} // Parses.
        public StringBuffer appendTo(StringBuffer sb) {...} // Formats.
        public String toString() {
            return appendTo(new StringBuffer()).toString();
        }
    }

This class is public domain (not copyrighted).

Author:Jean-Marie Dautelle
Version:4.6, June 22, 2003
/** * <p> * This class provides utility methods to parse <code>CharSequence</code> into primitive types and to format primitive * types into <code>StringBuffer</code>. * </p> * <p> * Methods from this utility class <b>do not create temporary objects</b> and are typically faster than standard library * methods (e.g {@link #parseDouble} is up to 15x faster than <code>Double.parseDouble</code>). * </p> * For class instances, formatting is typically performed using specialized <code>java.text.Format</code> * (<code>Locale</code> sensitive) and/or using conventional methods (class sensitive). For example: * * <pre> * public class Foo { * public static Foo valueOf(CharSequence chars) {...} // Parses. * public StringBuffer appendTo(StringBuffer sb) {...} // Formats. * public String toString() { * return appendTo(new StringBuffer()).toString(); * } * } * </pre> * <p> * <i> This class is <b>public domain</b> (not copyrighted).</i> * </p> * * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a> * @version 4.6, June 22, 2003 */
public final class TypeFormat {
Holds the characters used to represent numbers.
/** * Holds the characters used to represent numbers. */
private final static char[] DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
Default constructor (forbids derivation).
/** * Default constructor (forbids derivation). */
private TypeFormat() { }
Searches for a particular sequence within a character sequence (general purpose parsing function).
Params:
  • pattern – the character sequence to search for.
  • chars – the character sequence being searched.
  • fromIndex – the index in chars to start the search from.
Returns:the index in the range [fromIndex, chars.length()-pattern.length()] or -1 if the character sequence is not found.
/** * Searches for a particular sequence within a character sequence (general purpose parsing function). * * @param pattern the character sequence to search for. * @param chars the character sequence being searched. * @param fromIndex the index in <code>chars</code> to start the search from. * @return the index in the range <code>[fromIndex, chars.length()-pattern.length()]</code> or <code>-1</code> if * the character sequence is not found. */
public static int indexOf( CharSequence pattern, CharSequence chars, int fromIndex ) { int patternLength = pattern.length(); fromIndex = Math.max( 0, fromIndex ); if ( patternLength != 0 ) { // At least one character to search for. char firstChar = pattern.charAt( 0 ); int last = chars.length() - patternLength; for ( int i = fromIndex; i <= last; i++ ) { if ( chars.charAt( i ) == firstChar ) { boolean match = true; for ( int j = 1; j < patternLength; j++ ) { if ( chars.charAt( i + j ) != pattern.charAt( j ) ) { match = false; break; } } if ( match ) { return i; } } } return -1; } else { return Math.min( 0, fromIndex ); } }
Parses the specified CharSequence as a boolean.
Params:
  • chars – the character sequence to parse.
Returns:the corresponding boolean.
/** * Parses the specified <code>CharSequence</code> as a <code>boolean</code>. * * @param chars the character sequence to parse. * @return the corresponding <code>boolean</code>. */
public static boolean parseBoolean( CharSequence chars ) { return ( chars.length() == 4 ) && ( chars.charAt( 0 ) == 't' || chars.charAt( 0 ) == 'T' ) && ( chars.charAt( 1 ) == 'r' || chars.charAt( 1 ) == 'R' ) && ( chars.charAt( 2 ) == 'u' || chars.charAt( 2 ) == 'U' ) && ( chars.charAt( 3 ) == 'e' || chars.charAt( 3 ) == 'E' ); }
Parses the specified CharSequence as a signed decimal short.
Params:
  • chars – the character sequence to parse.
Throws:
See Also:
Returns:parseShort(chars, 10)
/** * Parses the specified <code>CharSequence</code> as a signed decimal <code>short</code>. * * @param chars the character sequence to parse. * @return <code>parseShort(chars, 10)</code> * @throws NumberFormatException if the specified character sequence does not contain a parsable <code>short</code>. * @see #parseShort(CharSequence, int) */
public static short parseShort( CharSequence chars ) { return parseShort( chars, 10 ); }
Parses the specified CharSequence as a signed short in the specified radix. The characters in the string must all be digits of the specified radix, except the first character which may be a plus sign '+' or a minus sign '-'.
Params:
  • chars – the character sequence to parse.
  • radix – the radix to be used while parsing.
Throws:
Returns:the corresponding short.
/** * Parses the specified <code>CharSequence</code> as a signed <code>short</code> in the specified radix. The * characters in the string must all be digits of the specified radix, except the first character which may be a * plus sign <code>'+'</code> or a minus sign <code>'-'</code>. * * @param chars the character sequence to parse. * @param radix the radix to be used while parsing. * @return the corresponding <code>short</code>. * @throws NumberFormatException if the specified character sequence does not contain a parsable <code>short</code>. */
public static short parseShort( CharSequence chars, int radix ) { try { boolean isNegative = ( chars.charAt( 0 ) == '-' ) ? true : false; int result = 0; int limit = ( isNegative ) ? Short.MIN_VALUE : -Short.MAX_VALUE; int multmin = limit / radix; int length = chars.length(); int i = ( isNegative || ( chars.charAt( 0 ) == '+' ) ) ? 1 : 0; while ( true ) { int digit = Character.digit( chars.charAt( i ), radix ); int tmp = result * radix; if ( ( digit < 0 ) || ( result < multmin ) || ( tmp < limit + digit ) ) { // Overflow. throw new NumberFormatException( "For input characters: \"" + chars.toString() + "\"" ); } // Accumulates negatively. result = tmp - digit; if ( ++i >= length ) { break; } } return (short) ( isNegative ? result : -result ); } catch ( IndexOutOfBoundsException e ) { throw new NumberFormatException( "For input characters: \"" + chars.toString() + "\"" ); } }
Parses the specified CharSequence as a signed decimal int.
Params:
  • chars – the character sequence to parse.
Throws:
See Also:
Returns:parseInt(chars, 10)
/** * Parses the specified <code>CharSequence</code> as a signed decimal <code>int</code>. * * @param chars the character sequence to parse. * @return <code>parseInt(chars, 10)</code> * @throws NumberFormatException if the specified character sequence does not contain a parsable <code>int</code>. * @see #parseInt(CharSequence, int) */
public static int parseInt( CharSequence chars ) { return parseInt( chars, 10 ); }
Parses the specified CharSequence as a signed int in the specified radix. The characters in the string must all be digits of the specified radix, except the first character which may be a plus sign '+' or a minus sign '-'.
Params:
  • chars – the character sequence to parse.
  • radix – the radix to be used while parsing.
Throws:
Returns:the corresponding int.
/** * Parses the specified <code>CharSequence</code> as a signed <code>int</code> in the specified radix. The * characters in the string must all be digits of the specified radix, except the first character which may be a * plus sign <code>'+'</code> or a minus sign <code>'-'</code>. * * @param chars the character sequence to parse. * @param radix the radix to be used while parsing. * @return the corresponding <code>int</code>. * @throws NumberFormatException if the specified character sequence does not contain a parsable <code>int</code>. */
public static int parseInt( CharSequence chars, int radix ) { try { boolean isNegative = ( chars.charAt( 0 ) == '-' ) ? true : false; int result = 0; int limit = ( isNegative ) ? Integer.MIN_VALUE : -Integer.MAX_VALUE; int multmin = limit / radix; int length = chars.length(); int i = ( isNegative || ( chars.charAt( 0 ) == '+' ) ) ? 1 : 0; while ( true ) { int digit = Character.digit( chars.charAt( i ), radix ); int tmp = result * radix; if ( ( digit < 0 ) || ( result < multmin ) || ( tmp < limit + digit ) ) { // Overflow. throw new NumberFormatException( "For input characters: \"" + chars.toString() + "\"" ); } // Accumulates negatively to avoid surprises near MAX_VALUE result = tmp - digit; if ( ++i >= length ) { break; } } return isNegative ? result : -result; } catch ( IndexOutOfBoundsException e ) { throw new NumberFormatException( "For input characters: \"" + chars.toString() + "\"" ); } }
Parses the specified CharSequence as a signed decimal long.
Params:
  • chars – the character sequence to parse.
Throws:
See Also:
Returns:parseLong(chars, 10)
/** * Parses the specified <code>CharSequence</code> as a signed decimal <code>long</code>. * * @param chars the character sequence to parse. * @return <code>parseLong(chars, 10)</code> * @throws NumberFormatException if the specified character sequence does not contain a parsable <code>long</code>. * @see #parseLong(CharSequence, int) */
public static long parseLong( CharSequence chars ) { return parseLong( chars, 10 ); }
Parses the specified CharSequence as a signed long in the specified radix. The characters in the string must all be digits of the specified radix, except the first character which may be a plus sign '+' or a minus sign '-'.
Params:
  • chars – the character sequence to parse.
  • radix – the radix to be used while parsing.
Throws:
Returns:the corresponding long.
/** * Parses the specified <code>CharSequence</code> as a signed <code>long</code> in the specified radix. The * characters in the string must all be digits of the specified radix, except the first character which may be a * plus sign <code>'+'</code> or a minus sign <code>'-'</code>. * * @param chars the character sequence to parse. * @param radix the radix to be used while parsing. * @return the corresponding <code>long</code>. * @throws NumberFormatException if the specified character sequence does not contain a parsable <code>long</code>. */
public static long parseLong( CharSequence chars, int radix ) { try { boolean isNegative = ( chars.charAt( 0 ) == '-' ) ? true : false; long result = 0; long limit = ( isNegative ) ? Long.MIN_VALUE : -Long.MAX_VALUE; long multmin = limit / radix; int length = chars.length(); int i = ( isNegative || ( chars.charAt( 0 ) == '+' ) ) ? 1 : 0; while ( true ) { int digit = Character.digit( chars.charAt( i ), radix ); long tmp = result * radix; if ( ( digit < 0 ) || ( result < multmin ) || ( tmp < limit + digit ) ) { // Overflow. throw new NumberFormatException( "For input characters: \"" + chars.toString() + "\"" ); } // Accumulates negatively to avoid surprises near MAX_VALUE result = tmp - digit; if ( ++i >= length ) { break; } } return isNegative ? result : -result; } catch ( IndexOutOfBoundsException e ) { throw new NumberFormatException( "For input characters: \"" + chars.toString() + "\"" ); } }
Parses this CharSequence as a float.
Params:
  • chars – the character sequence to parse.
Throws:
Returns:the float number represented by the specified character sequence.
/** * Parses this <code>CharSequence</code> as a <code>float</code>. * * @param chars the character sequence to parse. * @return the float number represented by the specified character sequence. * @throws NumberFormatException if the character sequence does not contain a parsable <code>float</code>. */
public static float parseFloat( CharSequence chars ) { double d = parseDouble( chars ); if ( ( d >= Float.MIN_VALUE ) && ( d <= Float.MAX_VALUE ) ) { return (float) d; } else { throw new NumberFormatException( "Float overflow for input characters: \"" + chars.toString() + "\"" ); } }
Parses this CharSequence as a double.
Params:
  • chars – the character sequence to parse.
Throws:
Returns:the double number represented by this character sequence.
/** * Parses this <code>CharSequence</code> as a <code>double</code>. * * @param chars the character sequence to parse. * @return the double number represented by this character sequence. * @throws NumberFormatException if the character sequence does not contain a parsable <code>double</code>. */
public static double parseDouble( CharSequence chars ) throws NumberFormatException { try { int length = chars.length(); double result = 0.0; int exp = 0; boolean isNegative = ( chars.charAt( 0 ) == '-' ) ? true : false; int i = ( isNegative || ( chars.charAt( 0 ) == '+' ) ) ? 1 : 0; // Checks special cases NaN or Infinity. if ( ( chars.charAt( i ) == 'N' ) || ( chars.charAt( i ) == 'I' ) ) { if ( chars.toString().equals( "NaN" ) ) { return Double.NaN; } else if ( chars.subSequence( i, length ).toString().equals( "Infinity" ) ) { return isNegative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY; } } // Reads decimal number. boolean fraction = false; while ( true ) { char c = chars.charAt( i ); if ( ( c == '.' ) && ( !fraction ) ) { fraction = true; } else if ( ( c == 'e' ) || ( c == 'E' ) ) { break; } else if ( ( c >= '0' ) && ( c <= '9' ) ) { result = result * 10 + ( c - '0' ); if ( fraction ) { exp--; } } else { throw new NumberFormatException( "For input characters: \"" + chars.toString() + "\"" ); } if ( ++i >= length ) { break; } } result = isNegative ? -result : result; // Reads exponent (if any). if ( i < length ) { i++; boolean negE = ( chars.charAt( i ) == '-' ) ? true : false; i = ( negE || ( chars.charAt( i ) == '+' ) ) ? i + 1 : i; int valE = 0; while ( true ) { char c = chars.charAt( i ); if ( ( c >= '0' ) && ( c <= '9' ) ) { valE = valE * 10 + ( c - '0' ); if ( valE > 10000000 ) { // Hard-limit to avoid overflow. valE = 10000000; } } else { throw new NumberFormatException( "For input characters: \"" + chars.toString() + "\"" ); } if ( ++i >= length ) { break; } } exp += negE ? -valE : valE; } // Returns product decimal number with exponent. return multE( result, exp ); } catch ( IndexOutOfBoundsException e ) { throw new NumberFormatException( "For input characters: \"" + chars.toString() + "\"" ); } }
Formats the specified boolean and appends the resulting text to the StringBuffer argument.
Params:
  • b – a boolean.
  • sb – the StringBuffer to append.
See Also:
Returns:the specified StringBuffer object.
/** * Formats the specified <code>boolean</code> and appends the resulting text to the <code>StringBuffer</code> * argument. * * @param b a <code>boolean</code>. * @param sb the <code>StringBuffer</code> to append. * @return the specified <code>StringBuffer</code> object. * @see #parseBoolean */
public static StringBuffer format( boolean b, StringBuffer sb ) { return b ? sb.append( "true" ) : sb.append( "false" ); }
Formats the specified short and appends the resulting text (decimal representation) to the StringBuffer argument.

Note: This method is preferred to StringBuffer.append(short) as it does not create temporary String objects (several times faster for small numbers).

Params:
  • s – the short number.
  • sb – the StringBuffer to append.
See Also:
Returns:the specified StringBuffer object.
/** * Formats the specified <code>short</code> and appends the resulting text (decimal representation) to the * <code>StringBuffer</code> argument. * <p> * Note: This method is preferred to <code>StringBuffer.append(short) * </code> as it does not create temporary <code>String</code> objects (several times faster for small * numbers). * </p> * * @param s the <code>short</code> number. * @param sb the <code>StringBuffer</code> to append. * @return the specified <code>StringBuffer</code> object. * @see #parseShort */
public static StringBuffer format( short s, StringBuffer sb ) { return format( (int) s, sb ); // Forwards to int formatting (fast). }
Formats the specified short in the specified radix and appends the resulting text to the StringBuffer argument.
Params:
  • s – the short number.
  • radix – the radix.
  • sb – the StringBuffer to append.
See Also:
Returns:the specified StringBuffer object.
/** * Formats the specified <code>short</code> in the specified radix and appends the resulting text to the * <code>StringBuffer</code> argument. * * @param s the <code>short</code> number. * @param radix the radix. * @param sb the <code>StringBuffer</code> to append. * @return the specified <code>StringBuffer</code> object. * @see #parseShort(CharSequence, int) throws IllegalArgumentException if radix is not in [2 .. 36] range. */
public static StringBuffer format( short s, int radix, StringBuffer sb ) { return format( (int) s, radix, sb ); // Forwards to int formatting (fast). }
Formats the specified int and appends the resulting text (decimal representation) to the StringBuffer argument.

Note: This method is preferred to StringBuffer.append(int) as it does not create temporary String objects (several times faster for small numbers).

Params:
  • i – the int number.
  • sb – the StringBuffer to append.
See Also:
Returns:the specified StringBuffer object.
/** * Formats the specified <code>int</code> and appends the resulting text (decimal representation) to the * <code>StringBuffer</code> argument. * <p> * Note: This method is preferred to <code>StringBuffer.append(int) * </code> as it does not create temporary <code>String</code> objects (several times faster for small * numbers). * </p> * * @param i the <code>int</code> number. * @param sb the <code>StringBuffer</code> to append. * @return the specified <code>StringBuffer</code> object. * @see #parseInt */
public static StringBuffer format( int i, StringBuffer sb ) { if ( i <= 0 ) { if ( i == Integer.MIN_VALUE ) { // Negation would overflow. return sb.append( "-2147483648" ); // 11 char max. } else if ( i == 0 ) { return sb.append( '0' ); } i = -i; sb.append( '-' ); } int j = 1; for ( ; ( j < 10 ) && ( i >= INT_POW_10[j] ); j++ ) { } // POW_10[j] > i >= POW_10[j-1] for ( j--; j >= 0; j-- ) { int pow10 = INT_POW_10[j]; int digit = i / pow10; i -= digit * pow10; sb.append( DIGITS[digit] ); } return sb; } private static final int[] INT_POW_10 = new int[10]; static { int pow = 1; for ( int i = 0; i < 10; i++ ) { INT_POW_10[i] = pow; pow *= 10; } }
Formats the specified int in the specified radix and appends the resulting text to the StringBuffer argument.
Params:
  • i – the int number.
  • radix – the radix.
  • sb – the StringBuffer to append.
See Also:
Returns:the specified StringBuffer object.
/** * Formats the specified <code>int</code> in the specified radix and appends the resulting text to the * <code>StringBuffer</code> argument. * * @param i the <code>int</code> number. * @param radix the radix. * @param sb the <code>StringBuffer</code> to append. * @return the specified <code>StringBuffer</code> object. * @see #parseInt(CharSequence, int) throws IllegalArgumentException if radix is not in [2 .. 36] range. */
public static StringBuffer format( int i, int radix, StringBuffer sb ) { if ( radix == 10 ) { return format( i, sb ); // Faster version. } else if ( radix < 2 || radix > 36 ) { throw new IllegalArgumentException( "radix: " + radix ); } if ( i < 0 ) { sb.append( '-' ); } else { i = -i; } format2( i, radix, sb ); return sb; } private static void format2( int i, int radix, StringBuffer sb ) { if ( i <= -radix ) { format2( i / radix, radix, sb ); sb.append( DIGITS[-( i % radix )] ); } else { sb.append( DIGITS[-i] ); } }
Formats the specified long and appends the resulting text (decimal representation) to the StringBuffer argument.

Note: This method is preferred to StringBuffer.append(long) as it does not create temporary String objects (several times faster for small numbers).

Params:
  • l – the long number.
  • sb – the StringBuffer to append.
See Also:
Returns:the specified StringBuffer object.
/** * Formats the specified <code>long</code> and appends the resulting text (decimal representation) to the * <code>StringBuffer</code> argument. * <p> * Note: This method is preferred to <code>StringBuffer.append(long) * </code> as it does not create temporary <code>String</code> objects (several times faster for small * numbers). * </p> * * @param l the <code>long</code> number. * @param sb the <code>StringBuffer</code> to append. * @return the specified <code>StringBuffer</code> object. * @see #parseLong */
public static StringBuffer format( long l, StringBuffer sb ) { if ( l <= 0 ) { if ( l == Long.MIN_VALUE ) { // Negation would overflow. return sb.append( "-9223372036854775808" ); // 20 characters max. } else if ( l == 0 ) { return sb.append( '0' ); } l = -l; sb.append( '-' ); } int j = 1; for ( ; ( j < 19 ) && ( l >= LONG_POW_10[j] ); j++ ) { } // POW_10[j] > l >= POW_10[j-1] for ( j--; j >= 0; j-- ) { long pow10 = LONG_POW_10[j]; int digit = (int) ( l / pow10 ); l -= digit * pow10; sb.append( DIGITS[digit] ); } return sb; } private static final long[] LONG_POW_10 = new long[19]; static { long pow = 1; for ( int i = 0; i < 19; i++ ) { LONG_POW_10[i] = pow; pow *= 10; } }
Formats the specified long in the specified radix and appends the resulting text to the StringBuffer argument.
Params:
  • l – the long number.
  • radix – the radix.
  • sb – the StringBuffer to append.
See Also:
Returns:the specified StringBuffer object.
/** * Formats the specified <code>long</code> in the specified radix and appends the resulting text to the * <code>StringBuffer</code> argument. * * @param l the <code>long</code> number. * @param radix the radix. * @param sb the <code>StringBuffer</code> to append. * @return the specified <code>StringBuffer</code> object. * @see #parseLong(CharSequence, int) throws IllegalArgumentException if radix is not in [2 .. 36] range. */
public static StringBuffer format( long l, int radix, StringBuffer sb ) { if ( radix == 10 ) { return format( l, sb ); // Faster version. } else if ( radix < 2 || radix > 36 ) { throw new IllegalArgumentException( "radix: " + radix ); } if ( l < 0 ) { sb.append( '-' ); } else { l = -l; } format2( l, radix, sb ); return sb; } private static void format2( long l, int radix, StringBuffer sb ) { if ( l <= -radix ) { format2( l / radix, radix, sb ); sb.append( DIGITS[(int) -( l % radix )] ); } else { sb.append( DIGITS[(int) -l] ); } }
Formats the specified float and appends the resulting text to the StringBuffer argument.
Params:
  • f – the float number.
  • sb – the StringBuffer to append.
See Also:
Returns:format(f, 0.0f, sb)
/** * Formats the specified <code>float</code> and appends the resulting text to the <code>StringBuffer</code> * argument. * * @param f the <code>float</code> number. * @param sb the <code>StringBuffer</code> to append. * @return <code>format(f, 0.0f, sb)</code> * @see #format(float, float, StringBuffer) */
public static StringBuffer format( float f, StringBuffer sb ) { return format( f, 0.0f, sb ); }
Formats the specified float and appends the resulting text to the StringBuffer argument; the number of significative digits is deduced from the specified precision. All digits at least as significant as the specified precision are represented. For example:
  • format(5.6f, 0.01f, sb) appends "5.60"
  • format(5.6f, 0.1f, sb) appends "5.6"
  • format(5.6f, 1f, sb) appends "6"
If the precision is 0.0f, the precision is assumed to be the intrinsic float precision (64 bits IEEE 754 format); no formatting is performed, all significant digits are displayed and trailing zeros are removed.
Params:
  • f – the float number.
  • precision – the maximum weight of the last digit represented.
  • sb – the StringBuffer to append.
Throws:
Returns:the specified StringBuffer object.
/** * Formats the specified <code>float</code> and appends the resulting text to the <code>StringBuffer</code> * argument; the number of significative digits is deduced from the specified precision. All digits at least as * significant as the specified precision are represented. For example: * <ul> * <li><code>format(5.6f, 0.01f, sb)</code> appends <code>"5.60"</code></li> * <li><code>format(5.6f, 0.1f, sb)</code> appends <code>"5.6"</code></li> * <li><code>format(5.6f, 1f, sb)</code> appends <code>"6"</code></li> * </ul> * If the precision is <code>0.0f</code>, the precision is assumed to be the intrinsic <code>float</code> precision * (64 bits IEEE 754 format); no formatting is performed, all significant digits are displayed and trailing zeros * are removed. * * @param f the <code>float</code> number. * @param precision the maximum weight of the last digit represented. * @param sb the <code>StringBuffer</code> to append. * @return the specified <code>StringBuffer</code> object. * @throws IllegalArgumentException if the specified precision is negative or would result in too many digits (19+). */
public static StringBuffer format( float f, float precision, StringBuffer sb ) { // Adjusts precision. boolean precisionOnLastDigit; if ( precision > 0.0f ) { precisionOnLastDigit = true; } else if ( precision == 0.0f ) { if ( f != 0.0f ) { precisionOnLastDigit = false; precision = Math.max( Math.abs( f * FLOAT_RELATIVE_ERROR ), Float.MIN_VALUE ); } else { return sb.append( "0.0" ); // Exact zero. } } else { throw new IllegalArgumentException( "precision: Negative values not allowed" ); } return format( f, precision, precisionOnLastDigit, sb ); }
Formats the specified double and appends the resulting text to the StringBuffer argument.

Note : This method is preferred to StringBuffer.append(double) or even String.valueOf(double) as it does not create temporary String or FloatingDecimal objects (several times faster, e.g. 15x faster for Double.MAX_VALUE).

Params:
  • d – the double number.
  • sb – the StringBuffer to append.
See Also:
Returns:format(d, 0.0, sb)
/** * Formats the specified <code>double</code> and appends the resulting text to the <code>StringBuffer</code> * argument. * <p> * Note : This method is preferred to <code>StringBuffer.append(double) * </code> or even <code>String.valueOf(double)</code> as it does not create temporary * <code>String</code> or <code> * FloatingDecimal</code> objects (several times faster, e.g. 15x faster for * <code>Double.MAX_VALUE</code>). * </p> * * @param d the <code>double</code> number. * @param sb the <code>StringBuffer</code> to append. * @return <code>format(d, 0.0, sb)</code> * @see #format(double, double, StringBuffer) */
public static StringBuffer format( double d, StringBuffer sb ) { return format( d, 0.0, sb ); }
Formats the specified double and appends the resulting text to the StringBuffer argument; the number of significand digits is specified as integer argument.
Params:
  • d – the double number.
  • digits – the number of significand digits (excludes exponent).
  • sb – the StringBuffer to append.
Throws:
Returns:the specified StringBuffer object.
/** * Formats the specified <code>double</code> and appends the resulting text to the <code>StringBuffer</code> * argument; the number of significand digits is specified as integer argument. * * @param d the <code>double</code> number. * @param digits the number of significand digits (excludes exponent). * @param sb the <code>StringBuffer</code> to append. * @return the specified <code>StringBuffer</code> object. * @throws IllegalArgumentException if the number of digits is not in range <code>[1..19]</code>. */
public static StringBuffer format( double d, int digits, StringBuffer sb ) { if ( ( digits >= 1 ) && ( digits <= 19 ) ) { double precision = Math.abs( d / DOUBLE_POW_10[digits - 1] ); return format( d, precision, sb ); } else { throw new java.lang.IllegalArgumentException( "digits: " + digits + " is not in range [1 .. 19]" ); } }
Formats the specified double and appends the resulting text to the StringBuffer argument; the number of significative digits is deduced from the specified precision. All digits at least as significant as the specified precision are represented. For example:
  • format(5.6, 0.01, sb) appends "5.60"
  • format(5.6, 0.1, sb) appends "5.6"
  • format(5.6, 1, sb) appends "6"
If the precision is 0.0, the precision is assumed to be the intrinsic double precision (64 bits IEEE 754 format); no formatting is performed, all significant digits are displayed and trailing zeros are removed.
Params:
  • d – the double number.
  • precision – the maximum weight of the last digit represented.
  • sb – the StringBuffer to append.
Throws:
Returns:the specified StringBuffer object.
/** * Formats the specified <code>double</code> and appends the resulting text to the <code>StringBuffer</code> * argument; the number of significative digits is deduced from the specified precision. All digits at least as * significant as the specified precision are represented. For example: * <ul> * <li><code>format(5.6, 0.01, sb)</code> appends <code>"5.60"</code></li> * <li><code>format(5.6, 0.1, sb)</code> appends <code>"5.6"</code></li> * <li><code>format(5.6, 1, sb)</code> appends <code>"6"</code></li> * </ul> * If the precision is <code>0.0</code>, the precision is assumed to be the intrinsic <code>double</code> precision * (64 bits IEEE 754 format); no formatting is performed, all significant digits are displayed and trailing zeros * are removed. * * @param d the <code>double</code> number. * @param precision the maximum weight of the last digit represented. * @param sb the <code>StringBuffer</code> to append. * @return the specified <code>StringBuffer</code> object. * @throws IllegalArgumentException if the specified precision is negative or would result in too many digits (19+). */
public static StringBuffer format( double d, double precision, StringBuffer sb ) { // Adjusts precision. boolean precisionOnLastDigit = false; if ( precision > 0.0 ) { precisionOnLastDigit = true; } else if ( precision == 0.0 ) { if ( d != 0.0 ) { precision = Math.max( Math.abs( d * DOUBLE_RELATIVE_ERROR ), Double.MIN_VALUE ); } else { return sb.append( "0.0" ); // Exact zero. } } else if ( precision < 0.0 ) { // Not NaN throw new IllegalArgumentException( "precision: Negative values not allowed" ); } return format( d, precision, precisionOnLastDigit, sb ); }
Formats the specified double and appends the resulting text to the StringBuffer argument; the number of significative digits is deduced from the specified precision.
Params:
  • d – the double number.
  • precision – the maximum weight of the last digit represented.
  • precisionOnLastDigit – indicates if the number of digits is deduced from the specified precision.
  • sb – the StringBuffer to append.
Returns:the specified StringBuffer object.
/** * Formats the specified <code>double</code> and appends the resulting text to the <code>StringBuffer</code> * argument; the number of significative digits is deduced from the specified precision. * * @param d the <code>double</code> number. * @param precision the maximum weight of the last digit represented. * @param precisionOnLastDigit indicates if the number of digits is deduced from the specified precision. * @param sb the <code>StringBuffer</code> to append. * @return the specified <code>StringBuffer</code> object. */
private static StringBuffer format( double d, double precision, boolean precisionOnLastDigit, StringBuffer sb ) { // Special cases. if ( Double.isNaN( d ) ) { return sb.append( "NaN" ); } else if ( Double.isInfinite( d ) ) { return ( d >= 0 ) ? sb.append( "Infinity" ) : sb.append( "-Infinity" ); } if ( d < 0 ) { d = -d; sb.append( '-' ); } // Formats decimal part. int rank = (int) Math.floor( Math.log( precision ) / LOG_10 ); double digitValue = multE( d, -rank ); if ( digitValue >= Long.MAX_VALUE ) { throw new IllegalArgumentException( "Specified precision would result in too many digits" ); } int digitStart = sb.length(); format( Math.round( digitValue ), sb ); int digitLength = sb.length() - digitStart; int dotPos = digitLength + rank; boolean useScientificNotation = false; // Inserts dot ('.') if ( ( dotPos <= -LEADING_ZEROS.length ) || ( dotPos > digitLength ) ) { // Scientific notation has to be used ("x.xxxEyy"). sb.insert( digitStart + 1, '.' ); useScientificNotation = true; } else if ( dotPos > 0 ) { // Dot within the string ("xxxx.xxxxx"). sb.insert( digitStart + dotPos, '.' ); } else { // Leading zeros ("0.xxxxx"). sb.insert( digitStart, LEADING_ZEROS[-dotPos] ); } // Removes trailing zeros. if ( !precisionOnLastDigit ) { int newLength = sb.length(); do { newLength--; } while ( sb.charAt( newLength ) == '0' ); sb.setLength( newLength + 1 ); } // Avoids trailing '.' if ( sb.charAt( sb.length() - 1 ) == '.' ) { if ( precisionOnLastDigit ) { sb.setLength( sb.length() - 1 ); // Prefers "xxx" to "xxx." } else { sb.append( '0' ); // Prefer "xxx.0" to "xxx." } } // Writes exponent. if ( useScientificNotation ) { sb.append( 'E' ); format( dotPos - 1, sb ); } return sb; } private static final double LOG_10 = Math.log( 10 ); private static final float FLOAT_RELATIVE_ERROR = (float) Math.pow( 2, -24 ); private static final double DOUBLE_RELATIVE_ERROR = Math.pow( 2, -53 ); private static String[] LEADING_ZEROS = { "0.", "0.0", "0.00" };
Returns the product of the specified value with 10 raised at the specified power exponent.
Params:
  • value – the value.
  • E – the exponent.
Returns:value * 10^E
/** * Returns the product of the specified value with <code>10</code> raised at the specified power exponent. * * @param value the value. * @param E the exponent. * @return <code>value * 10^E</code> */
private static final double multE( double value, int E ) { if ( E >= 0 ) { if ( E <= 308 ) { // Max: 1.7976931348623157E+308 return value * DOUBLE_POW_10[E]; } else { value *= 1E21; // Exact multiplicand. E = Math.min( 308, E - 21 ); return value * DOUBLE_POW_10[E]; } } else { if ( E >= -308 ) { return value / DOUBLE_POW_10[-E]; } else { // Min: 4.9E-324 value /= 1E21; // Exact divisor. E = Math.max( -308, E + 21 ); return value / DOUBLE_POW_10[-E]; } } } // Note: Approximation for exponents > 21. This may introduce round-off // errors (e.g. 1E23 represented as "9.999999999999999E22"). private static final double[] DOUBLE_POW_10 = new double[] { 1E000, 1E001, 1E002, 1E003, 1E004, 1E005, 1E006, 1E007, 1E008, 1E009, 1E010, 1E011, 1E012, 1E013, 1E014, 1E015, 1E016, 1E017, 1E018, 1E019, 1E020, 1E021, 1E022, 1E023, 1E024, 1E025, 1E026, 1E027, 1E028, 1E029, 1E030, 1E031, 1E032, 1E033, 1E034, 1E035, 1E036, 1E037, 1E038, 1E039, 1E040, 1E041, 1E042, 1E043, 1E044, 1E045, 1E046, 1E047, 1E048, 1E049, 1E050, 1E051, 1E052, 1E053, 1E054, 1E055, 1E056, 1E057, 1E058, 1E059, 1E060, 1E061, 1E062, 1E063, 1E064, 1E065, 1E066, 1E067, 1E068, 1E069, 1E070, 1E071, 1E072, 1E073, 1E074, 1E075, 1E076, 1E077, 1E078, 1E079, 1E080, 1E081, 1E082, 1E083, 1E084, 1E085, 1E086, 1E087, 1E088, 1E089, 1E090, 1E091, 1E092, 1E093, 1E094, 1E095, 1E096, 1E097, 1E098, 1E099, 1E100, 1E101, 1E102, 1E103, 1E104, 1E105, 1E106, 1E107, 1E108, 1E109, 1E110, 1E111, 1E112, 1E113, 1E114, 1E115, 1E116, 1E117, 1E118, 1E119, 1E120, 1E121, 1E122, 1E123, 1E124, 1E125, 1E126, 1E127, 1E128, 1E129, 1E130, 1E131, 1E132, 1E133, 1E134, 1E135, 1E136, 1E137, 1E138, 1E139, 1E140, 1E141, 1E142, 1E143, 1E144, 1E145, 1E146, 1E147, 1E148, 1E149, 1E150, 1E151, 1E152, 1E153, 1E154, 1E155, 1E156, 1E157, 1E158, 1E159, 1E160, 1E161, 1E162, 1E163, 1E164, 1E165, 1E166, 1E167, 1E168, 1E169, 1E170, 1E171, 1E172, 1E173, 1E174, 1E175, 1E176, 1E177, 1E178, 1E179, 1E180, 1E181, 1E182, 1E183, 1E184, 1E185, 1E186, 1E187, 1E188, 1E189, 1E190, 1E191, 1E192, 1E193, 1E194, 1E195, 1E196, 1E197, 1E198, 1E199, 1E200, 1E201, 1E202, 1E203, 1E204, 1E205, 1E206, 1E207, 1E208, 1E209, 1E210, 1E211, 1E212, 1E213, 1E214, 1E215, 1E216, 1E217, 1E218, 1E219, 1E220, 1E221, 1E222, 1E223, 1E224, 1E225, 1E226, 1E227, 1E228, 1E229, 1E230, 1E231, 1E232, 1E233, 1E234, 1E235, 1E236, 1E237, 1E238, 1E239, 1E240, 1E241, 1E242, 1E243, 1E244, 1E245, 1E246, 1E247, 1E248, 1E249, 1E250, 1E251, 1E252, 1E253, 1E254, 1E255, 1E256, 1E257, 1E258, 1E259, 1E260, 1E261, 1E262, 1E263, 1E264, 1E265, 1E266, 1E267, 1E268, 1E269, 1E270, 1E271, 1E272, 1E273, 1E274, 1E275, 1E276, 1E277, 1E278, 1E279, 1E280, 1E281, 1E282, 1E283, 1E284, 1E285, 1E286, 1E287, 1E288, 1E289, 1E290, 1E291, 1E292, 1E293, 1E294, 1E295, 1E296, 1E297, 1E298, 1E299, 1E300, 1E301, 1E302, 1E303, 1E304, 1E305, 1E306, 1E307, 1E308 }; }