FileDocCategorySizeDatePackage
ExponentialFormat.javaAPI DocExample6512Sun Mar 28 19:09:18 BST 1999None

ExponentialFormat.java

import java.text.*;
import java.io.*;
import java.util.*;


/**
 * Concrete class for formatting large and small numbers, allowing a variety
 * of exponential/scientific notation
 * @see          java.util.Format
 * @see          java.text.NumberFormat
 * @version      1.0 25 Jan 1998
 * @author       Elliotte Rusty Harold
 */
public class ExponentialFormat extends NumberFormat {

  // might make this only a number format
  DecimalFormatSymbols symbols;
  DecimalFormat parser;
  
  public ExponentialFormat() {
    this(new DecimalFormat());
  }

  /**
   * Create an ExponentialFormat from the given format and the symbols
   * for the default locale. 
   * <p>
   * @param format The decimal format that will parse parts of the exponential.
   */
  public ExponentialFormat(DecimalFormat format) {
    this.parser = format;
    this.symbols = format.getDecimalFormatSymbols();
    this.parser.setGroupingUsed(false);
  }
  
  public StringBuffer format(double number, StringBuffer toAppendTo, 
   FieldPosition pos) {

     if (Double.isNaN(number)) {
      toAppendTo.append(symbols.getNaN());
    } 
    else if (number < 0) {
      toAppendTo.append(symbols.getMinusSign());
      number = -number;
    }
    // now we just have to format a non-negative number
    if (Double.isInfinite(number)) {
       toAppendTo.append(symbols.getInfinity());
    } 
    else {
      int maxFractionDigits = this.getMaximumFractionDigits();
      if (maxFractionDigits <= 0) maxFractionDigits = 1;
      int maxIntegerDigits = this.getMaximumIntegerDigits();
      if (maxIntegerDigits <= 0) maxIntegerDigits = 1;
      int minIntegerDigits = this.getMinimumIntegerDigits();
      if (minIntegerDigits <= 0) minIntegerDigits = 1;
      int minFractionDigits = this.getMinimumFractionDigits();
      if (minFractionDigits <= 0) minFractionDigits = 1;
      if (number == 0.0) {
        for (int i = 0; i < minIntegerDigits; i++) {
          toAppendTo.append(symbols.getZeroDigit());
        }
        toAppendTo.append(symbols.getDecimalSeparator());
        for (int i = 0; i < minFractionDigits; i++) {
          toAppendTo.append(symbols.getZeroDigit());
        }
        toAppendTo.append("E+000");
      }
      else { // positive number
        // find integer, fraction, and exponent      
        // this method creates some round-off error but is relatively easy 
        // to understand. If round-off is a concern
        // an alternative method that treats the double as a binary number
        // may be seen in the source code for java.lang.FloatingDecimal
        double exponent = Math.floor(Math.log(number) / Math.log(10));
        double normalized = number / Math.pow(10, exponent);
        for (int i = 1; i < minIntegerDigits; i++) {
          normalized *= 10;
          exponent--;
        }
        parser.setMinimumFractionDigits(minFractionDigits);
        parser.format(normalized, toAppendTo, pos);
        toAppendTo.append('E');
        if (exponent >= 0) toAppendTo.append('+');
        toAppendTo.append((int) exponent);
      }
    }
    return toAppendTo;
  
  }

  public StringBuffer format(long number, StringBuffer toAppendTo, 
   FieldPosition pos) {

    if (number < 0) {
      toAppendTo.append(symbols.getMinusSign());
      number = -number;
    }

    int maxFractionDigits = this.getMaximumFractionDigits();
    if (maxFractionDigits <= 0) maxFractionDigits = 1;
    int maxIntegerDigits = this.getMaximumIntegerDigits();
    if (maxIntegerDigits <= 0) maxIntegerDigits = 1;
    int minIntegerDigits = this.getMinimumIntegerDigits();
    if (minIntegerDigits <= 0) minIntegerDigits = 1;
    int minFractionDigits = this.getMinimumFractionDigits();
    if (minFractionDigits <= 0) minFractionDigits = 1;
    if (number == 0) {
      for (int i = 0; i < minIntegerDigits; i++) {
        toAppendTo.append(symbols.getZeroDigit());
      }
      toAppendTo.append(symbols.getDecimalSeparator());
      for (int i = 0; i < minFractionDigits; i++) {
        toAppendTo.append(symbols.getZeroDigit());
      }
        toAppendTo.append("E+000");
      }
    else { // positive number
      // find integer, fraction, and exponent      

      int exponent = (int) Math.floor(Math.log(number) / Math.log(10));
      exponent -= minIntegerDigits - 1;
      String digits = Long.toString(number);
      while (digits.length() < minIntegerDigits + maxFractionDigits) {
        digits += '0';
      }
      String integerField = digits.substring(0, minIntegerDigits);
      String fractionField = digits.substring(minIntegerDigits, 
       minIntegerDigits+maxFractionDigits);

      toAppendTo.append(integerField);
      toAppendTo.append(symbols.getDecimalSeparator());
      toAppendTo.append(fractionField);
      toAppendTo.append('E');
      if (exponent > 0) toAppendTo.append('+');
      toAppendTo.append(exponent);
    }

    return toAppendTo;

  }
  
  public Number parse(String text, ParsePosition parsePosition) {
  
    int oldIndex = parsePosition.getIndex();

    try {
      double result = parser.parse(text, parsePosition).doubleValue();
      int eposition = text.toUpperCase().indexOf('E');
      if (eposition != -1) {
        // advance past the E
        parsePosition.setIndex(parsePosition.getIndex() + 1);
        int exponent = parser.parse(text, parsePosition).intValue();
        result *= Math.pow(10, exponent);
      }
      return new Double(result);
    }
    catch (Exception e) {
      parsePosition.setIndex(oldIndex);
      return null;
    }
    
  }

  public Object clone() {

    ExponentialFormat theClone = (ExponentialFormat) super.clone();
    theClone.parser = (DecimalFormat) parser.clone();
    theClone.symbols = (DecimalFormatSymbols) 
     theClone.parser.getDecimalFormatSymbols();
    return theClone;
    
  }

  /**
   * Overrides equals
   */
  public boolean equals(Object o) {
  
    if (!super.equals(o)) return false;
    ExponentialFormat other = (ExponentialFormat) o;
    other.symbols = other.parser.getDecimalFormatSymbols();
    if (!this.parser.equals(other.parser)) return false;
    if (!this.symbols.equals(other.symbols)) return false;
    return true;
    
  }

  /**
   * Overrides hashCode
   */
  public int hashCode() {
    return super.hashCode() * 31 + parser.getNegativePrefix().hashCode();
  }

}