package naturalLanguage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import lipstone.joshua.customStructures.lists.SortedList;
import lipstone.joshua.parser.Parser;
import lipstone.joshua.parser.exceptions.ParserException;
import lipstone.joshua.parser.types.BigDec;
import lipstone.joshua.parser.util.ConsCell;
import lipstone.joshua.parser.util.ConsType;
import lipstone.joshua.parser.util.LengthComparison;
public class Units {
private HashMap<String, Unit> units;
private static final String[] SI = {"meter", "second", "gram", "ampere", "kelvin", "mole", "candela", "byte"};
private HashMap<String, BigDec> prefixes;
private HashMap<String, String> abbreviatedPrefixes;
private TreeMap<String, String> unitAbbreviations;
private final NaturalLanguage nl;
private static final String prefixAbbreviations = "(y|z|a|f|p|n|m|c|d|da|h|k|M|G|T|P|E|Y)";
private static final String[] alphabet = {"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"};
private SortedList<String> allUnits;
private static final BigDec TEN = new BigDec(10);
private Parser parser;
public Units(Parser parser, NaturalLanguage nl) {
this.parser = parser;
this.nl = nl;
units = new HashMap<String, Unit>();
prefixes = new HashMap<String, BigDec>();
abbreviatedPrefixes = new HashMap<String, String>();
unitAbbreviations = new TreeMap<String, String>(new LengthComparison());
allUnits = new SortedList<String>(new LengthComparison());
//I know, but it is slightly faster than using an array and iterating through while converting to BigDec
prefixes.put("yocto", new BigDec(-8));
prefixes.put("zepto", new BigDec(-7));
prefixes.put("atto", new BigDec(-6));
prefixes.put("femto", new BigDec(-5));
prefixes.put("pico", new BigDec(-4));
prefixes.put("nano", new BigDec(-3));
prefixes.put("micro", new BigDec(-2));
prefixes.put("milli", new BigDec(-1));
prefixes.put("mili", new BigDec(-1));
prefixes.put("centi", new BigDec(-2.0 / 3.0));
prefixes.put("deci", new BigDec(-1.0 / 3.0));
prefixes.put("deca", new BigDec(1.0 / 3.0));
prefixes.put("hecto", new BigDec(2.0 / 3.0));
prefixes.put("milli", BigDec.ONE);
prefixes.put("kilo", BigDec.ONE);
prefixes.put("mega", new BigDec(2));
prefixes.put("giga", new BigDec(3));
prefixes.put("tera", new BigDec(4));
prefixes.put("peta", new BigDec(5));
prefixes.put("exa", new BigDec(6));
prefixes.put("zetta", new BigDec(7));
prefixes.put("yotta", new BigDec(8));
abbreviatedPrefixes.put("y", "yocto");
abbreviatedPrefixes.put("z", "zepto");
abbreviatedPrefixes.put("a", "atto");
abbreviatedPrefixes.put("f", "femto");
abbreviatedPrefixes.put("p", "pico");
abbreviatedPrefixes.put("n", "nano");
abbreviatedPrefixes.put("m", "milli");
abbreviatedPrefixes.put("c", "centi");
abbreviatedPrefixes.put("d", "deci");
abbreviatedPrefixes.put("da", "deca");
abbreviatedPrefixes.put("h", "hecto");
abbreviatedPrefixes.put("k", "kilo");
abbreviatedPrefixes.put("M", "mega");
abbreviatedPrefixes.put("G", "giga");
abbreviatedPrefixes.put("T", "tera");
abbreviatedPrefixes.put("P", "peta");
abbreviatedPrefixes.put("E", "exa");
abbreviatedPrefixes.put("Y", "yotta");
loadUnits();
}
/**
* Run a unit conversion
*
* @param input
* the unit conversion
* @param parser
* the parser that precipitated this method call
* @return the units converted from the input units to the output units
* @throws ParserException
*/
public BigDec convertUnits(ConsCell leftUnits, ConsCell rightUnits) throws ParserException {
return getFactor(leftUnits).divide(getFactor(rightUnits));
}
private BigDec getFactor(ConsCell units) throws ParserException {
ConsCell current = units;
BigDec factor = BigDec.ONE;
do {
boolean divide = current.getPreviousConsCell().getCarType() == ConsType.OPERATOR && (char) current.getPreviousConsCell().getCar() == '/';
BigDec partial;
if (current.getCarType() == ConsType.IDENTIFIER) {
String[] unit = stripPrefix((String) current.getCar());
partial = this.units.get(unit[1]).getFactor();
if (partial == null)
throw new InvalidUnitException(current.getCar() + " is not a valid unit.", nl);
if (unit[0].length() > 0)
partial = partial.multiply(prefixes.get(unit[0]));
}
else if (current.getCarType() == ConsType.CONS_CELL) {
ConsCell fact = parser.run(parser.preProcess((ConsCell) current.getCar()));
if (fact.getCarType() != ConsType.NUMBER || fact.length() != 1)
throw new InvalidUnitException(current.getCar() + " is not a valid unit set.", nl);
partial = (BigDec) fact.getCar();
}
else
continue;
if (current.getNextConsCell().getCarType() == ConsType.OPERATOR && (char) current.getNextConsCell().getCar() == '^') {
current.getNextConsCell().remove();
ConsCell power = current.getNextConsCell().singular();
if (power.getCarType() == ConsType.OPERATOR)
power.append(current.getNextConsCell().remove().singular());
else if (power.getCarType() == ConsType.CONS_CELL)
power = (ConsCell) power.getCar();
current.getNextConsCell().remove();
power = parser.run(parser.preProcess(power));
if (power.getCarType() != ConsType.NUMBER || power.length() != 1)
throw new InvalidUnitException(current.getCar() + " is raised to an invalid power.", nl);
partial = partial.pow((BigDec) power.getCar());
}
factor = divide ? factor.divide(partial) : factor.multiply(partial);
} while (!(current = current.getNextConsCell()).isNull());
return factor;
}
private String[] stripPrefix(String unit) throws InvalidUnitException {
Matcher m = nl.getPrefixPattern().matcher(unit);
if (m.find() && m.start() == 0 && units.containsKey(unit.substring(m.end())))
return new String[]{nl.getAbbreviationPrefixes().get(m.group()), unit.substring(m.end())};
for (String prefix : nl.getAbbreviationPrefixes().values())
if ((m = Pattern.compile(prefix).matcher(unit)).find() && m.start() == 0 && units.containsKey(unit.substring(m.end())))
return new String[]{m.group(), unit.substring(m.end())};
return new String[]{"", unit};
}
/*String convertUnits(String input, Parser parser) throws NumberFormatException, ParserException {
String output = "";
input = NaturalLanguage.parse(input, parser);
//Split the input string into its three subcomponents: quantity, initial units, final units
ArrayList<String> parts = parser.fromCommaList(input);
parts.set(0, temperatureUnits(parts, parser));
parts.set(1, expandAbbreviations(parts.get(1)));
parts.set(2, expandAbbreviations(parts.get(2)));
for (int i = 1; i < parts.size(); i++) {
parts.set(i, parts.get(i).replaceAll("[/\\\\]", " per "));
parts.set(i, parts.get(i).replaceAll("\\Q*\\E", " "));
//In case the other replacements cause multiple spaces
while (parts.get(i).contains(" "))
parts.set(i, parts.get(i).replaceAll(" ", " "));
}
//Determine the conversion factor
BigDec factors[] = {BigDec.ONE, BigDec.ONE};
for (int i = 0; i < 2; i++)
factors[i] = getFactor(parts.get(i + 1), parser);
//Convert the units
output = parser.run(parser.preProcess(parts.get(0) + "*" + factors[0] + "/" + factors[1]));
return output;
}
String expandAbbreviations(String input) {
for (String abbreviation : unitAbbreviations.keySet())
input = input.replaceAll("\\b" + abbreviation + "\\b", unitAbbreviations.get(abbreviation));
for (Unit unit : units) {
Pattern p = Pattern.compile("\\b" + prefixAbbreviations + "(" + unit.getName() + ")\\b");
Matcher m = p.matcher(input);
while (m.find()) {
input = input.substring(0, m.start(1)) + abbreviatedPrefixes.get(m.group(1)) + input.substring(m.start(2));
m = p.matcher(input);
}
p = Pattern.compile("\\b" + prefixAbbreviations + "(" + unit.getAbbreviations() + ")\\b");
m = p.matcher(input);
while (m.find()) {
input = input.substring(0, m.start(1)) + abbreviatedPrefixes.get(m.group(1)) + unitAbbreviations.get(m.group(2)) + input.substring(m.end(2));
m = p.matcher(input);
}
}
return input;
}
private BigDec getFactor(String unit, Parser parser) throws UndefinedResultException, UnbalancedParenthesesException {
BigDec factor = BigDec.ONE;
//Get the units
ArrayList<String> Units = new ArrayList<String>();
for (String str : unit.trim().split(" "))
Units.add(str);
Units = exponents(Units);
int per = 0;
boolean perParen = false, hasEnd = false;
for (int a = 0; a < Units.size(); a++) {
String u = Units.get(a);
BigDec tempFactor = BigDec.ZERO;
if (u.equalsIgnoreCase("per")) {
if (a < Units.size() - 1 && Units.get(a + 1).charAt(0) == '(')
perParen = !perParen;
per++;
a++;
u = Units.get(a);
}
for (int b = 0; b < units.size(); b++) {
Matcher m = Pattern.compile(units.get(b).getName(), Pattern.CASE_INSENSITIVE).matcher(u);
while (m.find()) {
BigDec power = BigDec.ONE, prefix = BigDec.ZERO;
int end = 0;
String tempKey = u.substring(0, m.start()).trim().toLowerCase();
if (prefixes.containsKey(tempKey))
prefix = prefix.add(prefixes.get(tempKey));
if (m.end() < u.length() - 1 && u.charAt(m.end()) == '^') {
if (u.charAt(m.end() + 1) == '(') {
end = parser.getEndIndex(u, m.end() + 1);
hasEnd = true;
}
else if (u.indexOf(')', m.end()) == -1)
end = u.length();
else
end = u.length() - 1;
power = power.multiply(new BigDec(u.substring(m.end() + 1, end)));
}
else if (m.end() < u.length() - 2 && u.charAt(m.end()) == 's' && u.charAt(m.end() + 1) == '^') {
if (u.charAt(m.end() + 2) == '(') {
end = parser.getEndIndex(u, m.end() + 2);
hasEnd = true;
}
else if (u.indexOf(')', m.end()) == -1)
end = u.length();
else
end = u.length() - 1;
power = power.multiply(new BigDec(u.substring(m.end() + 2, end)));
}
if (!isSI(units.get(b).getName()))
tempFactor = getFactor(units.get(b).getSI(), parser).multiply(new BigDec(units.get(b).getFactor())).multiply(new BigDec(1000).pow(new BigDec(prefix))).pow(power);
else
tempFactor = new BigDec(units.get(b).getFactor()).multiply(new BigDec(1000).pow(new BigDec(prefix))).pow(power);
}
}
if (per >= 1 || perParen) {
tempFactor = tempFactor.pow(BigDec.MINUSONE);
if (!perParen)
per--;
}
if (hasEnd && per >= 1) {
perParen = !perParen;
per--;
}
if (tempFactor.neq(BigDec.ZERO))
factor = factor.multiply(tempFactor);
}
return factor;
}
private String temperatureUnits(ArrayList<String> parts, Parser parser) throws ParserException {
BigDec temperature = new BigDec(parser.run(parts.get(0)));
//Convert to Kelvin
if (parts.size() < 3)
return parts.get(0);
for (int i = 0; i < parts.size(); i++)
if (!(parts.get(i) == null) && parts.get(i).length() < 1)
return parts.get(0);
if (parts.get(1).contains("fahrenheit") || parts.get(1).contains("farenheit") || parts.get(1).contains("Fahrenheit") || parts.get(1).contains("Farenheit"))
temperature = new BigDec(parser.run("5/9*(" + temperature + "+459.67)"));
if (parts.get(1).contains("Celcius") || parts.get(1).contains("celcius"))
temperature = temperature.add(new BigDec(273.15));
//Now convert to the end scale
if (parts.get(2).contains("fahrenheit") || parts.get(2).contains("farenheit") || parts.get(2).contains("Fahrenheit") || parts.get(2).contains("Farenheit"))
temperature = new BigDec(parser.run(temperature.toString() + "*9/5-459.67"));
if (parts.get(2).contains("Celcius") || parts.get(2).contains("celcius"))
temperature = temperature.subtract(new BigDec(273.15));
return temperature.toString();
}
public String DecimaltoIEEE754(String input, Parser parser) throws ParserException {
ArrayList<String> parts = parser.fromCommaList(input);
int exp = parser.IEEE754exp, sig = parser.IEEE754sig;
if (parts.size() == 3) {
try {
exp = Integer.parseInt(parts.get(1));
sig = Integer.parseInt(parts.get(2));
}
catch (NumberFormatException nfe) {}
}
return DecimaltoIEEE754(input, exp, sig, parser);
}
public String DecimaltoIEEE754(String input, int exp, int sig, Parser parser) throws ParserException {
input = parser.run(parser.preProcess(input));
BigDec number;
try {
number = new BigDec(input);
}
catch (NumberFormatException e) {
return input;
}
String[] parts = new String[]{"0", "", "1"};
if (number.lt(BigDec.ZERO)) //if number is negative, set the sign bit to 1
parts[0] = "1";
parts[2] = convertBases(input, TEN, new BigDec(2));
String[] baseExp = scientificNotation(parts[2], true, parser);
parts[1] = convertBases(parser.run(baseExp[1] + "+" + new Double((Math.pow(2, exp - 1) - 1)).toString()), TEN, new BigDec(2));
parts[2] = baseExp[0].replaceAll("\\Q.\\E", "");
if (parts[2].length() > 0)
parts[2] = parts[2].substring(1);
while (parts[1].length() < exp)
parts[1] = "0" + parts[1];
while (parts[2].length() < sig)
parts[2] = parts[2] + "0";
return parts[0] + parts[1] + parts[2];
}
public String IEEE754toDecimal(String input, Parser parser) throws ParserException {
ArrayList<String> parts = parser.fromCommaList(input);
int exp = parser.IEEE754exp, sig = parser.IEEE754sig;
if (parts.size() == 3) {
try {
exp = Integer.parseInt(parts.get(1));
sig = Integer.parseInt(parts.get(2));
}
catch (NumberFormatException nfe) {}
}
return IEEE754toDecimal(input, exp, sig, parser);
}
public String IEEE754toDecimal(String input, int exp, int sig, Parser parser) throws ParserException {
String output = "";
input = parser.run(parser.preProcess(input));
System.out.println("in: " + input);
input = fromScientificNotation(input);
System.out.println("in: " + input);
if (input.length() != (1 + exp + sig) || !parser.isNumber(input))
return input;
String[] parts = new String[3];
parts[0] = input.substring(0, 1);
parts[1] = input.substring(1, exp + 1);
parts[2] = input.substring(exp + 2);
if (parts[0].charAt(0) == '1')
output = "-";
parts[1] = parser.run(convertBases(parts[1], new BigDec(2), TEN) + "-" + (Math.pow(2, exp - 1) - 1));
parts[2] = "1" + parts[2].substring(0, new Double(parts[1]).intValue()) + "." + parts[2].substring(new Double(parts[1]).intValue());
output = output + parts[2];
return output;
}
public String convertBases(String input, Parser parser) throws ParserException {
String number = "";
BigDec initialBase = BigDec.ZERO, finalBase = TEN;
ArrayList<String> parts = parser.fromCommaList(input);
try {
initialBase = new BigDec(parser.run(parser.preProcess(parts.get(1))));
}
catch (NumberFormatException e) {
if (parts.get(1).equalsIgnoreCase("IEEE754")) {
parts.set(0, IEEE754toDecimal(parts.get(0), parser));
initialBase = TEN;
}
};
if (parts.size() > 2)
try {
finalBase = new BigDec(parser.run(parser.preProcess(parts.get(2))));
}
catch (NumberFormatException e) {
if (parts.get(2).equalsIgnoreCase("IEEE754")) {
parts.set(0, IEEE754toDecimal(parts.get(0), parser));
initialBase = TEN;
}
}
if (initialBase.eq(TEN))
number = parser.run(parser.preProcess(parts.get(0)));
else
number = parts.get(0);
System.out.println(number);
return convertBases(number, initialBase, finalBase);
}
public String convertBases(String number, BigDec initialBase, BigDec finalBase) throws UndefinedResultException {
if (number.length() < 1 || initialBase.lt(BigDec.ONE) || finalBase.lt(BigDec.ONE))
return "0.0";
if (initialBase.neq(TEN))
number = NtoDecimal(number, initialBase);
if (finalBase.neq(TEN))
number = DecimaltoN(number, finalBase);
if (number.length() > 1 && number.charAt(number.length() - 1) == '.')
number = number.substring(0, number.length() - 1);
return number;
}
public String NtoDecimal(String number, BigDec initialBase) throws UndefinedResultException {
BigDec output = BigDec.ZERO;
if (!number.contains("."))
number = number + ".";
int power = number.indexOf(".");
number = number.replaceAll("\\Q.\\E", "");
for (int i = 0; i < number.length(); i++) {
try {
output = output.add(new BigDec(number.substring(i, i + 1)).multiply(initialBase.pow(new BigDec(power - i - 1))));
}
catch (NumberFormatException e) {
if (betNum(number.charAt(i)) >= 0)
output = output.add(TEN.add(new BigDec(betNum(number.charAt(i)))).multiply(initialBase.pow(new BigDec(power - i - 1))));
}
}
return output.toString();
}
public String DecimaltoN(String number, BigDec finalBase) throws UndefinedResultException {
String output = "";
BigDec input = BigDec.ZERO;
try {
input = new BigDec(number);
}
catch (NumberFormatException e) {
return "0.0";
}
while (input.neq(BigDec.ZERO)) {
int temp = input.mod(finalBase).intValue();
if (temp > 9)
output = alphabet[temp - 10] + output;
else
output = temp + output;
input = new BigDec(input.divide(finalBase).toBigInt());
}
if (output.length() > 1 && output.charAt(0) == '0')
output = output.substring(1);
if (number.contains(".")) {
String decimal = fromScientificNotation(number), decOut = "";
decimal = decimal.substring(decimal.indexOf("."));
int max = (int) (decimal.length() * 1.5), i = 0;
BigDec dec = BigDec.ZERO;
do {
try {
dec = new BigDec(decimal).multiply(finalBase);
}
catch (NumberFormatException e) {
break;
}
if (dec.eq(BigDec.ZERO)) {
output = output + "." + decOut;
}
else {
int temp = dec.intValue();
if (temp > 9)
decOut = decOut + alphabet[temp - 10];
else
decOut = decOut + temp;
decimal = dec.toString();
decimal = decimal.substring(decimal.indexOf("."));
}
i++;
} while (dec.neq(BigDec.ZERO) && i < max);
if (i >= max)
output = output + "." + decOut;
}
return output;
}
private int betNum(Character num) {
for (int i = 0; i < alphabet.length; i++)
if (alphabet[i].equalsIgnoreCase(num.toString()))
return i;
return 0;
}*/
private void loadUnits() {
//base units
addUnit("meter", "meter", BigDec.ONE, "m");
addUnit("second", "second", BigDec.ONE, "s");
addUnit("gram", "gram", BigDec.ONE, "g");
addUnit("ampere", "ampere", BigDec.ONE, "A");
addUnit("kelvin", "kelvin", BigDec.ONE, "K");
addUnit("mole", "mole", BigDec.ONE, "mol");
addUnit("candela", "candela", BigDec.ONE, "cd");
addUnit("byte", "byte", BigDec.ONE, "b");
addUnit("radian", "radian", BigDec.ONE, "rad");
//SI abbreviations
addUnit("amp", "ampere", BigDec.ONE);
//angle
addUnit("degree", "radian", new BigDec(Math.PI / 180));
addUnit("grad", "radian", new BigDec(Math.PI / 200));
//distance
addUnit("mile", "meter", new BigDec(1609.34), "mi");
addUnit("f(o|e)\\1t", "meter", new BigDec(0.3048), "ft");
addUnit("inch", "meter", new BigDec(0.0254), "in");
addUnit("yard", "meter", new BigDec(0.9144), "yd");
//compensates for plural
addUnit("inche", "meter", new BigDec(0.0254));
//volume
addUnit("liter", "centimeter^3", new BigDec(1000), "L");
addUnit("litre", "centimeter^3", new BigDec(1000));
//time
addUnit("minute", "second", new BigDec(60));
addUnit("hour", "minute", new BigDec(60), "hr");
addUnit("day", "hour", new BigDec(24));
addUnit("week", "day", new BigDec(7));
addUnit("month", "day", new BigDec(30));
addUnit("year", "day", new BigDec(365), "yr");
//mass
addUnit("slug", "gram", new BigDec(14593.9029));
//temperature
addUnit("rankine", "kelvin", new BigDec(1.8));
//frequency
addUnit("hertz", "second^(-1)", BigDec.ONE, "Hz");
//force
addUnit("newton", "kilogram meter per (second^2)", BigDec.ONE, "N");
//pressure, stress
addUnit("pascal", "newton per (meter^2)", BigDec.ONE, "Pa");
addUnit("psi", "pascal", new BigDec(6894.75729));
//energy, work, heat
addUnit("joule", "newton meter", BigDec.ONE, "J");
addUnit("calorie", "joule", new BigDec(4.184), "cal");
addUnit("Calorie", "calorie", new BigDec(1000), "Cal");
//power, radiant flux
addUnit("watt", "joule per (second)", BigDec.ONE, "W");
//electric charge, quantity of electricity
addUnit("coulomb", "second ampere", BigDec.ONE, "C");
//voltage, electrical potential difference, electromotive force
addUnit("volt", "joule per (coulomb)", BigDec.ONE, "V");
//electric capacitance
addUnit("farad", "coulomb per (volt)", BigDec.ONE, "F");
//electric resistance, impedance, reactance
addUnit("ohm", "volt per (ampere)", BigDec.ONE);
//electrical conductance
addUnit("siemens", "ohm^(-1)", BigDec.ONE, "S");
//magnetic flux
addUnit("weber", "joule per (ampere)", BigDec.ONE, "Wb");
//magnetic field strength, magnetic flux density
addUnit("tesla", "volt second per (meter^2)", BigDec.ONE, "T");
//inductance
addUnit("henry", "volt second per (ampere)", BigDec.ONE, "H");
//luminous flux
addUnit("lumen", "candela", BigDec.ONE, "lm");
//illuminance
addUnit("lux", "lumen per (meter^2)", BigDec.ONE, "lx");
//radioactivity (decays per unit time)
addUnit("becquerel", "second^(-1)", BigDec.ONE, "Bq");
//absorbed dose (of ionizing radiation)
addUnit("gray", "joule per (kilogram)", BigDec.ONE, "Gy");
//equivalent dose (of ionizing radiation)
addUnit("sievert", "coulomb per (volt)", BigDec.ONE, "Sv");
//catalytic activity
addUnit("katal", "mole per (second)", BigDec.ONE, "kat");
//data
addUnit("bit", "byte", new BigDec(0.125));
addUnit("nibble", "byte", new BigDec(0.5));
}
public void addUnit(String name, String SI, BigDec SIfactor) {
addUnit(name, SI, SIfactor, new String[]{});
}
public void addUnit(String name, String SI, BigDec SIfactor, String... abbreviations) {
units.put(name, new Unit(name, SI, SIfactor, abbreviations));
for (String abbreviation : abbreviations)
unitAbbreviations.put(abbreviation, name);
for (String prefix : prefixes.keySet())
allUnits.add(prefix + name);
}
public boolean containsUnit(String input) {
for (int i = 0; i < units.size(); i++)
if (input.contains(units.get(i).getName()))
return true;
return false;
}
private boolean isSI(String unit) {
for (String str : SI)
if (unit.trim().equalsIgnoreCase(str))
return true;
return false;
}
private ArrayList<String> exponents(ArrayList<String> units) {
for (int i = 0; i < units.size(); i++) {
String u = units.get(i);
if ((u.equalsIgnoreCase("square") || u.equalsIgnoreCase("cubic")) && i < units.size() - 1) {
if (units.get(i + 1).charAt(units.get(i + 1).length()) == ')') {
if (u.equalsIgnoreCase("square"))
units.set(i + 1, units.get(i + 1).substring(0, units.get(i + 1).length() - 1) + "^2)");
else if (u.equalsIgnoreCase("cubic"))
units.set(i + 1, units.get(i + 1).substring(0, units.get(i + 1).length() - 1) + "^3)");
}
else {
if (u.equalsIgnoreCase("square"))
units.set(i + 1, units.get(i + 1).substring(0, units.get(i + 1).length()) + "^2");
else if (u.equalsIgnoreCase("cubic"))
units.set(i + 1, units.get(i + 1).substring(0, units.get(i + 1).length()) + "^3");
}
units.remove(i);
u = units.get(i);
}
if ((u.equalsIgnoreCase("squared") || u.equalsIgnoreCase("cubed")) && i >= 1) {
if (units.get(i - 1).charAt(units.get(i - 1).length()) == ')') {
if (u.equalsIgnoreCase("squared"))
units.set(i - 1, units.get(i - 1).substring(0, units.get(i - 1).length() - 1) + "^2)");
else if (u.equalsIgnoreCase("cubed"))
units.set(i - 1, units.get(i - 1).substring(0, units.get(i - 1).length() - 1) + "^3)");
}
else {
if (u.equalsIgnoreCase("squared"))
units.set(i - 1, units.get(i - 1).substring(0, units.get(i - 1).length()) + "^2");
else if (u.equalsIgnoreCase("cubed"))
units.set(i - 1, units.get(i - 1).substring(0, units.get(i - 1).length()) + "^3");
}
units.remove(i);
}
}
return units;
}
private String[] scientificNotation(String num, boolean array, Parser parser) {
String parts[] = new String[]{"", ""};//base, order
if (!num.contains("."))
num = num + ".0";
while (num.charAt(0) == '0' && num.charAt(1) != '.')
num = num.substring(1);
if (num.length() > 1) {
for (int i = 0; i < num.length(); i++)
if (parser.isNumber(num.charAt(i)) && num.charAt(i) != '0' && num.charAt(i) != '.') {
parts[1] = new BigDec(num.indexOf('.') - i - 1).toString();
break;
}
parts[0] = num.substring(0, 1) + "." + num.substring(1).replaceAll("\\Q.\\E", "");
}
else
return new String[]{num, "0"};
return parts;
}
private String fromScientificNotation(String num) {
String exp = "0";
if (num.contains("E")) {
exp = num.substring(num.indexOf("E") + 1);
num = num.substring(0, num.indexOf("E"));
}
if (num.contains("10^")) {
exp = num.substring(num.indexOf("*10^") + 4);
num = num.substring(0, num.indexOf("*10^"));
}
if (num.contains(".")) {
int index = num.indexOf("."), expo = new Double(exp).intValue();
while (num.length() < expo + index + 1)
num = num + "0";
num = num.substring(0, index) + num.substring(index + 1, index + 1 + expo) + "." + num.substring(index + 1 + expo);
}
return num;
}
/**
* Add a unit from a unit's data string
*
* @param data
* a <tt>String</tt> of the form <code>name : SI : factor : abbreviation</code> or
* <code>name : SI : factor</code> if there is no abbreviation
*/
public void addUnit(String data) {
String[] parts = data.split(" : ");
if (parts.length == 4)
addUnit(parts[0], parts[1], parts[2], parts[3]);
else
addUnit(parts[0], parts[1], parts[2], "");
}
/**
* Convenience method - calls {@link #addUnit(String, String, String, String)} with no abbreviation
*
* @param name
* the of the unit
* @param SI
* an equivalent unit (preferably in the SI system)
* @param factor
* the conversion factor between this unit and the unit in SI
*/
public void addUnit(String name, String SI, String factor) {
addUnit(name, SI, new BigDec(factor.trim()));
}
/**
* Adds a unit
*
* @param name
* the of the unit
* @param SI
* an equivalent unit (preferably in the SI system)
* @param factor
* the conversion factor between this unit and the unit in SI
* @param abbriviation
* the abbreviation for this unit
*/
public void addUnit(String name, String SI, String factor, String... abbriviation) {
addUnit(name, SI, new BigDec(factor.trim()), abbriviation);
}
public void removeUnit(String name) {
unitAbbreviations.clear();
for (int i = 0; i < units.size(); i++) {
if (units.get(i).getName().equals(name)) {
units.remove(i--);
continue;
}
for (String abbreviation : units.get(i).getAbbreviations())
unitAbbreviations.put(abbreviation, units.get(i).getName());
}
}
public HashMap<String, Unit> getUnits() {
return units;
}
public ArrayList<String> getUnitNames() {
return allUnits;
}
}