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();
}
}
|