/*
* Copyright 2006, United States Government as represented by the Administrator
* for the National Aeronautics and Space Administration. No copyright is
* claimed in the United States under Title 17, U.S. Code. All Other Rights
* Reserved.
*/
package gov.nasa.ial.mde.math;
import gov.nasa.ial.mde.properties.MdeSettings;
import gov.nasa.ial.mde.solver.MdeFeatureNode;
import gov.nasa.ial.mde.util.MathUtil;
import java.text.NumberFormat;
/**
* A model of a number.
*
* @version 1.0
* @since 1.0
*/
public class NumberModel {
//Might want to use BigDecimal instead or in addition
private double decimalValue;
private String approximateDecimalValue;
private String rationalValue;
private String quadraticValue;
private boolean isAnApproximation;
private int fractionDigits = -1; // use default if not set
private static final double EPSILON = 1.0e-10;
private static final int DEFAULT_FRACTION_DIGITS = 3;
@SuppressWarnings("unused")
private NumberModel() {
throw new RuntimeException("Default constructor not permitted");
}
/**
* Constructs a NumberModel with the specified decimal and a default
* search limit of 100.
*
* @param decimal the decimal value.
*/
public NumberModel(double decimal) {
this(decimal, 100);
} // end NumberModel(double decimal)
/**
* Constructs a NumberModel with the specified decimal and search limit.
*
* @param decimal the decimal value.
* @param searchLimit the search limit.
*/
public NumberModel(double decimal, int searchLimit) {
decimalValue = decimal;
if(MdeSettings.DEBUG){
System.out.println(decimalValue);
}
if (Double.isInfinite(decimal))
return;
constructApproximateDecimal();
rationalValue = MathUtil.getEquivalentRationalString(decimal, searchLimit);
quadraticValue = MathUtil.getQuadraticRepresentationString(decimal, searchLimit);
} // end NumberModel(double decimal, int searchLimit)
private void constructApproximateDecimal() {
NumberFormat n = NumberFormat.getInstance();
n.setMinimumFractionDigits(0);
n.setMaximumFractionDigits((fractionDigits > 0) ? fractionDigits : DEFAULT_FRACTION_DIGITS);
approximateDecimalValue = n.format(decimalValue);
if(MdeSettings.DEBUG){
System.out.println(approximateDecimalValue);
}
try {
approximateDecimalValue = approximateDecimalValue.replace(",","");
double d = new Double(approximateDecimalValue).doubleValue();
isAnApproximation = (Math.abs(d - decimalValue) > EPSILON
* (1.0 + Math.abs(d) + Math.abs(decimalValue)));
} // end try
catch (NumberFormatException nfe) {
throw new RuntimeException("Internal number format error");
} // end catch
} // end constructApproximateDecimal
/**
* Returns the decimal value.
*
* @return the decimal value.
*/
public double getDecimalValue() {
return decimalValue;
}
/**
* Returns the approximate decimal value.
*
* @return the approximate decimal value.
*/
public String getApproximateDecimalValue() {
return approximateDecimalValue;
} // end getApproximateDecimalValue
/**
* Returns the rational value.
*
* @return the rational value.
*/
public String getRationalValue() {
return rationalValue;
}
/**
* Returns the quadratic value.
*
* @return the quadratic value.
*/
public String getQuadraticValue() {
return quadraticValue;
}
/**
* Returns the string representation of the number model.
*
* @return the string representation of the number model.
* @see java.lang.Object#toString()
*/
public String toString() {
StringBuffer s = new StringBuffer("NumberModel:");
s.append("\ndecimalValue: " + decimalValue);
if (rationalValue != null) {
s.append("\nrationalValue: " + rationalValue);
} else {
s.append("\nNo rational representation was found.");
}
if (quadraticValue != null) {
s.append("\nquadraticValue: " + quadraticValue);
} else {
s.append("\nNo quadratic representation was found.");
}
return s.toString();
}
/**
* Returns the MDE Fedature Node for the number model.
*
* @return the MDE Fedature Node for the number model.
*/
public MdeFeatureNode getMFN() {
String temp;
MdeFeatureNode r = new MdeFeatureNode();
if (Double.isInfinite(decimalValue))
temp = (decimalValue > 0.0) ? "infinity" : "-infinity";
else if (Double.isNaN(decimalValue))
temp = "undefined";
else
temp = "" + decimalValue;
r.addKey("decimalValue");
r.addValue("decimalValue", temp);
if ((temp = getApproximateDecimalValue()) != null) {
r.addKey("approximateDecimalValue");
r.addValue("approximateDecimalValue", temp);
r.addKey("isApproximation");
r.addValue("isApproximation", "" + isAnApproximation);
} // end if
if ((temp = getRationalValue()) != null) {
r.addKey("rationalValue");
r.addValue("rationalValue", temp);
} // end if
if ((temp = getQuadraticValue()) != null) {
r.addKey("quadraticValue");
r.addValue("quadraticValue", temp);
} // end if
return r;
} // end getMFN
/**
* Returns the XML representation of the number model.
*
* @return the XML representation of the number model.
*/
public String getXML() {
StringBuffer s = new StringBuffer("");
s.append("\n <decimalValue>" + decimalValue + "</decimalValue>");
if (rationalValue != null) {
s.append("\n <rationalValue>" + rationalValue + "</rationalValue>");
}
if (quadraticValue != null) {
s.append("\n <quadraticValue>" + quadraticValue + "</quadraticValue>");
}
return s.toString();
}
// public static void main(String[] args) {
// try {
//
// if (args.length == 0) {
// java.io.InputStreamReader isr = new java.io.InputStreamReader(System.in);
// java.io.BufferedReader u = new java.io.BufferedReader(isr);
//
// while (true) {
// System.out.println("Enter a number (or CTRL-C to exit): ");
// Double d = new Double(u.readLine());
// double decimal = d.doubleValue();
// NumberModel nm = new NumberModel(decimal);
// System.out.println(nm);
// System.out.println("xml: " + nm.getXML());
// }
// }
//
// NumberModel nm = new NumberModel(new Double(args[0]).doubleValue());
//
// System.out.println(nm);
// System.out.println("xml: " + nm.getXML());
// } catch (Exception e) {
// System.out.println(e);
// }
// }
}