summaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/sevenUnits/unit/BritishImperial.java39
-rw-r--r--src/main/java/sevenUnits/unit/LinearUnitValue.java17
-rw-r--r--src/main/java/sevenUnits/unit/UnitDatabase.java55
-rw-r--r--src/main/java/sevenUnits/unit/UnitValue.java3
-rw-r--r--src/main/java/sevenUnits/utils/ConditionalExistenceCollections.java2
-rw-r--r--src/main/java/sevenUnits/utils/ExpressionParser.java12
-rw-r--r--src/main/java/sevenUnits/utils/ObjectProduct.java135
-rw-r--r--src/main/java/sevenUnits/utils/UncertainDouble.java15
8 files changed, 158 insertions, 120 deletions
diff --git a/src/main/java/sevenUnits/unit/BritishImperial.java b/src/main/java/sevenUnits/unit/BritishImperial.java
index 81a3f2a..743beeb 100644
--- a/src/main/java/sevenUnits/unit/BritishImperial.java
+++ b/src/main/java/sevenUnits/unit/BritishImperial.java
@@ -37,7 +37,7 @@ public final class BritishImperial {
public static final LinearUnit ROOD = Length.ROD.times(Length.FURLONG);
public static final LinearUnit ACRE = Length.FURLONG.times(Length.CHAIN);
}
-
+
/**
* Imperial units that measure length
*
@@ -46,7 +46,8 @@ public final class BritishImperial {
*/
public static final class Length {
/**
- * According to the International Yard and Pound of 1959, a yard is defined as exactly 0.9144 metres.
+ * According to the International Yard and Pound of 1959, a yard is
+ * defined as exactly 0.9144 metres.
*/
public static final LinearUnit YARD = Metric.METRE.times(0.9144);
public static final LinearUnit FOOT = YARD.dividedBy(3);
@@ -56,15 +57,15 @@ public final class BritishImperial {
public static final LinearUnit FURLONG = CHAIN.times(10);
public static final LinearUnit MILE = FURLONG.times(8);
public static final LinearUnit LEAGUE = MILE.times(3);
-
+
public static final LinearUnit NAUTICAL_MILE = Metric.METRE.times(1852);
public static final LinearUnit CABLE = NAUTICAL_MILE.dividedBy(10);
public static final LinearUnit FATHOM = CABLE.dividedBy(100);
-
+
public static final LinearUnit ROD = YARD.times(5.5);
public static final LinearUnit LINK = ROD.dividedBy(25);
}
-
+
/**
* British Imperial units that measure mass.
*
@@ -82,7 +83,7 @@ public final class BritishImperial {
public static final LinearUnit LONG_TON = HUNDREDWEIGHT.times(20);
public static final LinearUnit SLUG = Metric.KILOGRAM.times(14.59390294);
}
-
+
/**
* British Imperial units that measure volume
*
@@ -90,27 +91,33 @@ public final class BritishImperial {
* @since 2019-11-08
*/
public static final class Volume {
- public static final LinearUnit FLUID_OUNCE = Metric.LITRE.withPrefix(Metric.MILLI).times(28.4130625);
+ public static final LinearUnit FLUID_OUNCE = Metric.LITRE
+ .withPrefix(Metric.MILLI).times(28.4130625);
public static final LinearUnit GILL = FLUID_OUNCE.times(5);
public static final LinearUnit PINT = FLUID_OUNCE.times(20);
public static final LinearUnit QUART = PINT.times(2);
public static final LinearUnit GALLON = QUART.times(4);
public static final LinearUnit PECK = GALLON.times(2);
public static final LinearUnit BUSHEL = PECK.times(4);
-
+
public static final LinearUnit CUBIC_INCH = Length.INCH.toExponent(3);
public static final LinearUnit CUBIC_FOOT = Length.FOOT.toExponent(3);
public static final LinearUnit CUBIC_YARD = Length.YARD.toExponent(3);
public static final LinearUnit ACRE_FOOT = Area.ACRE.times(Length.FOOT);
}
-
- public static final LinearUnit OUNCE_FORCE = Mass.OUNCE.times(Metric.Constants.EARTH_GRAVITY);
- public static final LinearUnit POUND_FORCE = Mass.POUND.times(Metric.Constants.EARTH_GRAVITY);
-
- public static final LinearUnit BRITISH_THERMAL_UNIT = Metric.JOULE.times(1055.06);
+
+ public static final LinearUnit OUNCE_FORCE = Mass.OUNCE
+ .times(Metric.Constants.EARTH_GRAVITY);
+ public static final LinearUnit POUND_FORCE = Mass.POUND
+ .times(Metric.Constants.EARTH_GRAVITY);
+
+ public static final LinearUnit BRITISH_THERMAL_UNIT = Metric.JOULE
+ .times(1055.06);
public static final LinearUnit CALORIE = Metric.JOULE.times(4.184);
public static final LinearUnit KILOCALORIE = Metric.JOULE.times(4184);
-
- public static final Unit FAHRENHEIT = Unit.fromConversionFunctions(Metric.KELVIN.getBase(),
- tempK -> tempK * 1.8 - 459.67, tempF -> (tempF + 459.67) / 1.8);
+
+ public static final Unit FAHRENHEIT = Unit
+ .fromConversionFunctions(Metric.KELVIN.getBase(),
+ tempK -> tempK * 1.8 - 459.67, tempF -> (tempF + 459.67) / 1.8)
+ .withName(NameSymbol.of("degrees Fahrenheit", "\u00B0F"));
}
diff --git a/src/main/java/sevenUnits/unit/LinearUnitValue.java b/src/main/java/sevenUnits/unit/LinearUnitValue.java
index a36d568..a50e1f5 100644
--- a/src/main/java/sevenUnits/unit/LinearUnitValue.java
+++ b/src/main/java/sevenUnits/unit/LinearUnitValue.java
@@ -324,17 +324,18 @@ public final class LinearUnitValue {
// get rounded strings
// if showUncertainty is true, add brackets around the string
- final String valueString = showUncertainty ? "("
- : "" + this.value.toString(showUncertainty)
- + (showUncertainty ? ")" : "");
- final String baseValueString = showUncertainty ? "("
- : "" + baseValue.toString(showUncertainty)
- + (showUncertainty ? ")" : "");
+ final String valueString = (showUncertainty ? "(" : "")
+ + this.value.toString(showUncertainty)
+ + (showUncertainty ? ")" : "");
+ final String baseValueString = (showUncertainty ? "(" : "")
+ + baseValue.toString(showUncertainty)
+ + (showUncertainty ? ")" : "");
// create string
- if (primaryName.isEmpty() && symbol.isEmpty())
+ if (chosenName == null)
return String.format("%s unnamed unit (= %s %s)", valueString,
- baseValueString, this.unit.getBase());
+ baseValueString, this.unit.getBase()
+ .toString(unit -> unit.getSymbol().orElseThrow()));
else
return String.format("%s %s", valueString, chosenName);
}
diff --git a/src/main/java/sevenUnits/unit/UnitDatabase.java b/src/main/java/sevenUnits/unit/UnitDatabase.java
index b45d9cf..18ac619 100644
--- a/src/main/java/sevenUnits/unit/UnitDatabase.java
+++ b/src/main/java/sevenUnits/unit/UnitDatabase.java
@@ -243,7 +243,8 @@ public final class UnitDatabase {
return false;
else {
if (this.prefixNames.isEmpty())
- return this.unitNamePosition >= this.unitNames.size() - 1;
+ return this.prefixCoordinates.isEmpty()
+ && this.unitNamePosition < this.unitNames.size();
else
return true;
}
@@ -557,7 +558,8 @@ public final class UnitDatabase {
return false;
else {
if (this.prefixNames.isEmpty())
- return this.unitNamePosition >= this.unitNames.size() - 1;
+ return this.prefixCoordinates.isEmpty()
+ && this.unitNamePosition < this.unitNames.size();
else
return true;
}
@@ -1038,7 +1040,7 @@ public final class UnitDatabase {
@Override
public String toString() {
if (this.units.isEmpty() || this.prefixes.isEmpty())
- return super.toString();
+ return new HashMap<>(this).toString();
else
return String.format(
"Infinite map of name-unit entries created from units %s and prefixes %s",
@@ -1161,7 +1163,7 @@ public final class UnitDatabase {
* @return true if entry represents a removable duplicate entry of unitMap.
* @since 2021-05-22
*/
- private static boolean isRemovableDuplicate(Map<String, Unit> unitMap,
+ static boolean isRemovableDuplicate(Map<String, Unit> unitMap,
Entry<String, Unit> entry) {
for (final Entry<String, Unit> e : unitMap.entrySet()) {
final String name = e.getKey();
@@ -1344,10 +1346,10 @@ public final class UnitDatabase {
final String name = lineMatcher.group(1);
final String expression = lineMatcher.group(2);
- if (name.endsWith(" ")) {
- System.err.printf("Warning - line %d's dimension name ends in a space",
- lineCounter);
- }
+ // if (name.endsWith(" ")) {
+ // System.err.printf("Warning - line %d's dimension name ends in a space",
+ // lineCounter);
+ // }
// if expression is "!", search for an existing dimension
// if no unit found, throw an error
@@ -1360,7 +1362,7 @@ public final class UnitDatabase {
final ObjectProduct<BaseDimension> dimension;
try {
dimension = this.getDimensionFromExpression(expression);
- } catch (final IllegalArgumentException e) {
+ } catch (final IllegalArgumentException | NoSuchElementException e) {
System.err.printf("Parsing error on line %d:%n", lineCounter);
throw e;
}
@@ -1427,10 +1429,11 @@ public final class UnitDatabase {
final String expression = lineMatcher.group(2);
- if (name.endsWith(" ")) {
- System.err.printf("Warning - line %d's unit name ends in a space",
- lineCounter);
- }
+ // this code should never occur
+ // if (name.endsWith(" ")) {
+ // System.err.printf("Warning - line %d's unit name ends in a space",
+ // lineCounter);
+ // }
// if expression is "!", search for an existing unit
// if no unit found, throw an error
@@ -1443,7 +1446,8 @@ public final class UnitDatabase {
final UnitPrefix prefix;
try {
prefix = this.getPrefixFromExpression(expression);
- } catch (final IllegalArgumentException e) {
+ } catch (final IllegalArgumentException
+ | NoSuchElementException e) {
System.err.printf("Parsing error on line %d:%n", lineCounter);
throw e;
}
@@ -1453,7 +1457,8 @@ public final class UnitDatabase {
final Unit unit;
try {
unit = this.getUnitFromExpression(expression);
- } catch (final IllegalArgumentException e) {
+ } catch (final IllegalArgumentException
+ | NoSuchElementException e) {
System.err.printf("Parsing error on line %d:%n", lineCounter);
throw e;
}
@@ -1581,8 +1586,15 @@ public final class UnitDatabase {
}
return base.toExponent(exponent);
+ } else {
+ final ObjectProduct<BaseDimension> dimension = this.dimensions
+ .get(name);
+ if (dimension == null)
+ throw new NoSuchElementException(
+ "No dimension with name \"" + name + "\".");
+ else
+ return dimension;
}
- return this.dimensions.get(name);
}
/**
@@ -1635,7 +1647,7 @@ public final class UnitDatabase {
* @since 2019-03-22
* @since v0.2.0
*/
- private LinearUnit getLinearUnit(final String name) {
+ LinearUnit getLinearUnit(final String name) {
// see if I am using a function-unit like tempC(100)
Objects.requireNonNull(name, "name may not be null");
if (name.contains("(") && name.contains(")")) {
@@ -1670,7 +1682,7 @@ public final class UnitDatabase {
* @return {@code LinearUnitValue} instance
* @since 2020-08-04
*/
- private LinearUnitValue getLinearUnitValue(final String name) {
+ LinearUnitValue getLinearUnitValue(final String name) {
try {
// try to parse it as a number - otherwise it is not a number!
final BigDecimal number = new BigDecimal(name);
@@ -1695,7 +1707,12 @@ public final class UnitDatabase {
try {
return UnitPrefix.valueOf(Double.parseDouble(name));
} catch (final NumberFormatException e) {
- return this.prefixes.get(name);
+ final UnitPrefix prefix = this.prefixes.get(name);
+ if (prefix == null)
+ throw new NoSuchElementException(
+ "No prefix with name \"" + name + "\".");
+ else
+ return prefix;
}
}
diff --git a/src/main/java/sevenUnits/unit/UnitValue.java b/src/main/java/sevenUnits/unit/UnitValue.java
index 2fedd81..f6d18f8 100644
--- a/src/main/java/sevenUnits/unit/UnitValue.java
+++ b/src/main/java/sevenUnits/unit/UnitValue.java
@@ -163,7 +163,8 @@ public final class UnitValue {
if (primaryName.isEmpty() && symbol.isEmpty()) {
final double baseValue = this.getUnit().convertToBase(this.getValue());
return String.format("%s unnamed unit (= %s %s)", this.getValue(),
- baseValue, this.getUnit().getBase());
+ baseValue, this.getUnit().getBase()
+ .toString(unit -> unit.getSymbol().orElseThrow()));
} else {
final String unitName = symbol.orElse(primaryName.get());
return this.getValue() + " " + unitName;
diff --git a/src/main/java/sevenUnits/utils/ConditionalExistenceCollections.java b/src/main/java/sevenUnits/utils/ConditionalExistenceCollections.java
index 2adb579..bee4dd1 100644
--- a/src/main/java/sevenUnits/utils/ConditionalExistenceCollections.java
+++ b/src/main/java/sevenUnits/utils/ConditionalExistenceCollections.java
@@ -283,7 +283,7 @@ public final class ConditionalExistenceCollections {
@Override
public Set<K> keySet() {
- return conditionalExistenceSet(super.keySet(),
+ return conditionalExistenceSet(this.map.keySet(),
k -> this.entryExistenceCondition.test(this.getEntry(k)));
}
diff --git a/src/main/java/sevenUnits/utils/ExpressionParser.java b/src/main/java/sevenUnits/utils/ExpressionParser.java
index 1d3d44d..941c2a4 100644
--- a/src/main/java/sevenUnits/utils/ExpressionParser.java
+++ b/src/main/java/sevenUnits/utils/ExpressionParser.java
@@ -461,10 +461,12 @@ public final class ExpressionParser<T> {
*
* @param expression expression
* @return expression in RPN
+ * @throws IllegalArgumentException if expression is invalid (e.g.
+ * "{@code 3 *}")
* @since 2019-03-17
* @since v0.2.0
*/
- private String convertExpressionToReversePolish(final String expression) {
+ String convertExpressionToReversePolish(final String expression) {
Objects.requireNonNull(expression, "expression must not be null.");
final List<String> components = new ArrayList<>();
@@ -541,6 +543,9 @@ public final class ExpressionParser<T> {
switch (this
.getTokenType(components.get(highestPriorityOperatorPosition))) {
case UNARY_OPERATOR:
+ if (components.size() < 2)
+ throw new IllegalArgumentException(
+ "Invalid expression \"" + expression + "\"");
final String unaryOperator = components
.remove(highestPriorityOperatorPosition);
final String operand = components
@@ -549,6 +554,9 @@ public final class ExpressionParser<T> {
operand + " " + unaryOperator);
break;
case BINARY_OPERATOR:
+ if (components.size() < 3)
+ throw new IllegalArgumentException(
+ "Invalid expression \"" + expression + "\"");
final String binaryOperator = components
.remove(highestPriorityOperatorPosition);
final String operand1 = components
@@ -672,7 +680,7 @@ public final class ExpressionParser<T> {
* @since 2019-03-14
* @since v0.2.0
*/
- private T parseReversePolishExpression(final String expression) {
+ T parseReversePolishExpression(final String expression) {
Objects.requireNonNull(expression, "expression must not be null.");
final Deque<T> stack = new ArrayDeque<>();
diff --git a/src/main/java/sevenUnits/utils/ObjectProduct.java b/src/main/java/sevenUnits/utils/ObjectProduct.java
index 1dacb7d..5b1b739 100644
--- a/src/main/java/sevenUnits/utils/ObjectProduct.java
+++ b/src/main/java/sevenUnits/utils/ObjectProduct.java
@@ -27,8 +27,8 @@ import java.util.Set;
import java.util.function.Function;
/**
- * An immutable product of multiple objects of a type, such as base units. The objects can be multiplied and
- * exponentiated.
+ * An immutable product of multiple objects of a type, such as base units. The
+ * objects can be multiplied and exponentiated.
*
* @author Adrien Hopkins
* @since 2019-10-16
@@ -37,38 +37,35 @@ public final class ObjectProduct<T> {
/**
* Returns an empty ObjectProduct of a certain type
*
- * @param <T>
- * type of objects that can be multiplied
+ * @param <T> type of objects that can be multiplied
* @return empty product
* @since 2019-10-16
*/
public static final <T> ObjectProduct<T> empty() {
return new ObjectProduct<>(new HashMap<>());
}
-
+
/**
* Gets an {@code ObjectProduct} from an object-to-integer mapping
*
- * @param <T>
- * type of object in product
- * @param map
- * map mapping objects to exponents
+ * @param <T> type of object in product
+ * @param map map mapping objects to exponents
* @return object product
* @since 2019-10-16
*/
- public static final <T> ObjectProduct<T> fromExponentMapping(final Map<T, Integer> map) {
+ public static final <T> ObjectProduct<T> fromExponentMapping(
+ final Map<T, Integer> map) {
return new ObjectProduct<>(new HashMap<>(map));
}
-
+
/**
- * Gets an ObjectProduct that has one of the inputted argument, and nothing else.
+ * Gets an ObjectProduct that has one of the inputted argument, and nothing
+ * else.
*
- * @param object
- * object that will be in the product
+ * @param object object that will be in the product
* @return product
* @since 2019-10-16
- * @throws NullPointerException
- * if object is null
+ * @throws NullPointerException if object is null
*/
public static final <T> ObjectProduct<T> oneOf(final T object) {
Objects.requireNonNull(object, "object must not be null.");
@@ -76,35 +73,34 @@ public final class ObjectProduct<T> {
map.put(object, 1);
return new ObjectProduct<>(map);
}
-
+
/**
- * The objects that make up the product, mapped to their exponents. This map treats zero as null, and is immutable.
+ * The objects that make up the product, mapped to their exponents. This map
+ * treats zero as null, and is immutable.
*
* @since 2019-10-16
*/
final Map<T, Integer> exponents;
-
+
/**
* Creates the {@code ObjectProduct}.
*
- * @param exponents
- * objects that make up this product
+ * @param exponents objects that make up this product
* @since 2019-10-16
*/
private ObjectProduct(final Map<T, Integer> exponents) {
- this.exponents = Collections.unmodifiableMap(ConditionalExistenceCollections.conditionalExistenceMap(exponents,
- e -> !Integer.valueOf(0).equals(e.getValue())));
+ this.exponents = Collections.unmodifiableMap(
+ ConditionalExistenceCollections.conditionalExistenceMap(exponents,
+ e -> !Integer.valueOf(0).equals(e.getValue())));
}
-
+
/**
* Calculates the quotient of two products
*
- * @param other
- * other product
+ * @param other other product
* @return quotient of two products
* @since 2019-10-16
- * @throws NullPointerException
- * if other is null
+ * @throws NullPointerException if other is null
*/
public ObjectProduct<T> dividedBy(final ObjectProduct<T> other) {
Objects.requireNonNull(other, "other must not be null.");
@@ -112,17 +108,17 @@ public final class ObjectProduct<T> {
final Set<T> objects = new HashSet<>();
objects.addAll(this.getBaseSet());
objects.addAll(other.getBaseSet());
-
+
// get a list of all exponents
final Map<T, Integer> map = new HashMap<>(objects.size());
for (final T key : objects) {
map.put(key, this.getExponent(key) - other.getExponent(key));
}
-
+
// create the product
return new ObjectProduct<>(map);
}
-
+
// this method relies on the use of ZeroIsNullMap
@Override
public boolean equals(final Object obj) {
@@ -133,7 +129,7 @@ public final class ObjectProduct<T> {
final ObjectProduct<?> other = (ObjectProduct<?>) obj;
return Objects.equals(this.exponents, other.exponents);
}
-
+
/**
* @return immutable map mapping objects to exponents
* @since 2019-10-16
@@ -141,30 +137,31 @@ public final class ObjectProduct<T> {
public Map<T, Integer> exponentMap() {
return this.exponents;
}
-
+
/**
- * @return a set of all of the base objects with non-zero exponents that make up this dimension.
+ * @return a set of all of the base objects with non-zero exponents that make
+ * up this dimension.
* @since 2018-12-12
* @since v0.1.0
*/
public final Set<T> getBaseSet() {
final Set<T> dimensions = new HashSet<>();
-
- // add all dimensions with a nonzero exponent - zero exponents shouldn't be there in the first place
+
+ // add all dimensions with a nonzero exponent - zero exponents shouldn't
+ // be there in the first place
for (final T dimension : this.exponents.keySet()) {
if (!this.exponents.get(dimension).equals(0)) {
dimensions.add(dimension);
}
}
-
+
return dimensions;
}
-
+
/**
* Gets the exponent for a specific dimension.
*
- * @param dimension
- * dimension to check
+ * @param dimension dimension to check
* @return exponent for that dimension
* @since 2018-12-12
* @since v0.1.0
@@ -172,14 +169,15 @@ public final class ObjectProduct<T> {
public int getExponent(final T dimension) {
return this.exponents.getOrDefault(dimension, 0);
}
-
+
@Override
public int hashCode() {
return Objects.hash(this.exponents);
}
-
+
/**
- * @return true if this product is a single object, i.e. it has one exponent of one and no other nonzero exponents
+ * @return true if this product is a single object, i.e. it has one exponent
+ * of one and no other nonzero exponents
* @since 2019-10-16
*/
public boolean isSingleObject() {
@@ -194,16 +192,14 @@ public final class ObjectProduct<T> {
}
return oneCount == 1 && !twoOrMore;
}
-
+
/**
* Multiplies this product by another
*
- * @param other
- * other product
+ * @param other other product
* @return product of two products
* @since 2019-10-16
- * @throws NullPointerException
- * if other is null
+ * @throws NullPointerException if other is null
*/
public ObjectProduct<T> times(final ObjectProduct<T> other) {
Objects.requireNonNull(other, "other must not be null.");
@@ -211,22 +207,21 @@ public final class ObjectProduct<T> {
final Set<T> objects = new HashSet<>();
objects.addAll(this.getBaseSet());
objects.addAll(other.getBaseSet());
-
+
// get a list of all exponents
final Map<T, Integer> map = new HashMap<>(objects.size());
for (final T key : objects) {
map.put(key, this.getExponent(key) + other.getExponent(key));
}
-
+
// create the product
return new ObjectProduct<>(map);
}
-
+
/**
* Returns this product, but to an exponent
*
- * @param exponent
- * exponent
+ * @param exponent exponent
* @return result of exponentiation
* @since 2019-10-16
*/
@@ -237,11 +232,12 @@ public final class ObjectProduct<T> {
}
return new ObjectProduct<>(map);
}
-
+
/**
- * Converts this product to a string using the objects' {@link Object#toString()} method. If objects have a long
- * toString representation, it is recommended to use {@link #toString(Function)} instead to shorten the returned
- * string.
+ * Converts this product to a string using the objects'
+ * {@link Object#toString()} method. If objects have a long toString
+ * representation, it is recommended to use {@link #toString(Function)}
+ * instead to shorten the returned string.
*
* <p>
* {@inheritDoc}
@@ -250,35 +246,38 @@ public final class ObjectProduct<T> {
public String toString() {
return this.toString(Object::toString);
}
-
+
/**
- * Converts this product to a string. The objects that make up this product are represented by
- * {@code objectToString}
+ * Converts this product to a string. The objects that make up this product
+ * are represented by {@code objectToString}
*
- * @param objectToString
- * function to convert objects to strings
+ * @param objectToString function to convert objects to strings
* @return string representation of product
* @since 2019-10-16
*/
public String toString(final Function<T, String> objectToString) {
final List<String> positiveStringComponents = new ArrayList<>();
final List<String> negativeStringComponents = new ArrayList<>();
-
+
// for each base object that makes up this object, add it and its exponent
for (final T object : this.getBaseSet()) {
final int exponent = this.exponents.get(object);
- if (exponent > 0) {
- positiveStringComponents.add(String.format("%s^%d", objectToString.apply(object), exponent));
+ if (exponent > 1) {
+ positiveStringComponents.add(String.format("%s^%d",
+ objectToString.apply(object), exponent));
+ } else if (exponent == 1) {
+ positiveStringComponents.add(objectToString.apply(object));
} else if (exponent < 0) {
- negativeStringComponents.add(String.format("%s^%d", objectToString.apply(object), -exponent));
+ negativeStringComponents.add(String.format("%s^%d",
+ objectToString.apply(object), -exponent));
}
}
-
+
final String positiveString = positiveStringComponents.isEmpty() ? "1"
: String.join(" * ", positiveStringComponents);
final String negativeString = negativeStringComponents.isEmpty() ? ""
: " / " + String.join(" * ", negativeStringComponents);
-
+
return positiveString + negativeString;
}
}
diff --git a/src/main/java/sevenUnits/utils/UncertainDouble.java b/src/main/java/sevenUnits/utils/UncertainDouble.java
index 8fe4b31..fe41104 100644
--- a/src/main/java/sevenUnits/utils/UncertainDouble.java
+++ b/src/main/java/sevenUnits/utils/UncertainDouble.java
@@ -36,13 +36,14 @@ public final class UncertainDouble implements Comparable<UncertainDouble> {
*/
public static final UncertainDouble ZERO = UncertainDouble.of(0, 0);
+ static final String NUMBER_REGEX = "(\\d+(?:[\\.,]\\d+))";
+
/**
* A regular expression that can recognize toString forms
*/
- private static final Pattern TO_STRING = Pattern
- .compile("([a-zA-Z_0-9\\.\\,]+)" // a number
- // optional "± [number]"
- + "(?:\\s*(?:±|\\+-)\\s*([a-zA-Z_0-9\\.\\,]+))?");
+ static final Pattern TO_STRING = Pattern.compile(NUMBER_REGEX
+ // optional "± [number]"
+ + "(?:\\s*(?:±|\\+-)\\s*" + NUMBER_REGEX + ")?");
/**
* Parses a string in the form of {@link UncertainDouble#toString(boolean)}
@@ -60,10 +61,14 @@ public final class UncertainDouble implements Comparable<UncertainDouble> {
Objects.requireNonNull(s, "s may not be null");
final Matcher matcher = TO_STRING.matcher(s);
+ if (!matcher.matches())
+ throw new IllegalArgumentException(
+ "Could not parse stirng \"" + s + "\".");
+
double value, uncertainty;
try {
value = Double.parseDouble(matcher.group(1));
- } catch (IllegalStateException | NumberFormatException e) {
+ } catch (final NumberFormatException e) {
throw new IllegalArgumentException(
"String " + s + " not in correct format.");
}