package org.geogebra.web.html5.util;
import java.text.DecimalFormat;
import org.geogebra.common.util.ScientificFormatAdapter;
/**
* This code formats numbers in Scientific Notation. The input Number object is
* returned as a ScientificFormated string. There are two output styles: Pure
* and Standard scientific notation. Pure formatted numbers have precisely the
* number of digits specified by the significant digits (sigDig) parameter and
* always specify a Base 10 Exponential(E). Standard formated numbers have the
* number of digits specified by the significant digits (sigDig) parameter but
* will not have a Base 10 Exponential(E) if the number of digits in the
* mantissa <= maxWidth.
*
* @author Paul Spence
* @author Mark Donszelmann
* @version $Id: ScientificFormat.java,v 1.4 2009-06-22 02:18:22 hohenwarter Exp
* $
*/
public class ScientificFormat extends Format implements ScientificFormatAdapter {
/**
* The number of significant digits the number is formatted to is recorded
* by sigDigit. The maximum width allowed for the returned String is
* recorded by MaxWidth
*/
private int sigDigit = 5;
private int maxWidth = 8;
private boolean sciNote = false;
private DecimalFormat decimalFormat;
public ScientificFormat() {
}
/**
* Sets the significant digits, maximum allowable width and number
* formatting style (SciNote == true for Pure formatting).
*/
public ScientificFormat(int sigDigit, int maxWidth, boolean sciNote) {
setSigDigits(sigDigit);
setMaxWidth(maxWidth);
setScientificNotationStyle(sciNote);
}
/**
* Returns the number of significant digits
*/
@Override
public int getSigDigits() {
return sigDigit;
}
/**
* Returns the maximum allowable width of formatted number excluding any
* exponentials
*/
@Override
public int getMaxWidth() {
return maxWidth;
}
/**
* Returns the formatting style: True means Pure scientific formatting,
* False means standard.
*/
@Override
public boolean getScientificNotationStyle() {
return sciNote;
}
/**
* Sets the number of significant digits for the formatted number
*/
@Override
public void setSigDigits(int SigDigit) {
if (SigDigit < 1) {
throw new IllegalArgumentException("sigDigit");
}
sigDigit = SigDigit;
decimalFormat = null;
}
/**
* Sets the maximum allowable length of the formattted number mantissa
* before exponential notation is used.
*/
@Override
public void setMaxWidth(int mWidth) {
if (mWidth < 3) {
throw new IllegalArgumentException("maxWidth");
}
maxWidth = mWidth;
}
/**
* Sets the format style used. There are two output styles: Pure and
* Standard scientific notation. Pure formatted numbers have precisely the
* number of digits specified by the significant digits (sigDig) parameter
* and always specify a Base 10 Exponential(E). Standard formated numbers
* have the number of digits specified by the significant digits (sigDig)
* parameter but will not have a Base 10 Exponential(E) if the number of
* digits in the mantissa <= maxWidth.
*/
@Override
public void setScientificNotationStyle(boolean sciNote) {
this.sciNote = sciNote;
}
private static DecimalFormat getDecimalFormat(int sigDig) {
StringBuffer buffer = new StringBuffer("0.");
for (int i = 1; i < sigDig; i++) {
buffer.append('0');
}
buffer.append("E0");
return new DecimalFormat(buffer.toString());
}
/**
* Format the number using scientific notation
*/
@Override
public String format(double d) {
return format(d, sigDigit);
}
private String format(double d, int sigDig) {
// Delegate the hard part to decimalFormat
if (decimalFormat == null) {
decimalFormat = getDecimalFormat(sigDigit);
}
DecimalFormat format = (sigDig == sigDigit) ? decimalFormat
: getDecimalFormat(sigDig);
String preliminaryResult = format.format(d);
if (sciNote) {
return preliminaryResult;
}
int ePos = preliminaryResult.indexOf('E');
int exponent = Integer.parseInt(preliminaryResult.substring(ePos + 1)) + 1;
if (exponent > maxWidth) {
return preliminaryResult;
}
if (exponent < -maxWidth + sigDig + 1) {
return preliminaryResult;
}
// We need to fix up the result
int sign = preliminaryResult.charAt(0) == '-' ? 1 : 0;
StringBuffer result = new StringBuffer(preliminaryResult.substring(
sign, sign + 1) + preliminaryResult.substring(sign + 2, ePos));
if (exponent >= sigDig) {
for (int i = sigDig; i < exponent; i++) {
result.append('0');
}
} else if (exponent < 0) {
result.insert(0, ".");
for (int i = exponent; i < 0; i++) {
result.insert(1, '0');
}
} else {
result.insert(exponent, '.');
}
if (sign > 0) {
result.insert(0, '-');
}
return result.toString();
}
// /**
// * Format a number plus error using scientific notation
// */
// public String formatError(double d,double dx)
// {
// return format(dx, resolveErrorSigDigit(d, dx));
// }
}