summaryrefslogtreecommitdiff
path: root/src/main/java/sevenUnits/utils/UncertainDouble.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/sevenUnits/utils/UncertainDouble.java')
-rw-r--r--src/main/java/sevenUnits/utils/UncertainDouble.java144
1 files changed, 96 insertions, 48 deletions
diff --git a/src/main/java/sevenUnits/utils/UncertainDouble.java b/src/main/java/sevenUnits/utils/UncertainDouble.java
index ca94817..c70574a 100644
--- a/src/main/java/sevenUnits/utils/UncertainDouble.java
+++ b/src/main/java/sevenUnits/utils/UncertainDouble.java
@@ -35,21 +35,24 @@ public final class UncertainDouble implements Comparable<UncertainDouble> {
* The exact value 0
*/
public static final UncertainDouble ZERO = UncertainDouble.of(0, 0);
-
+
static final String NUMBER_REGEX = "(\\d+(?:[\\.,]\\d+))";
-
+
/**
* A regular expression that can recognize toString forms
*/
static final Pattern TO_STRING = Pattern.compile(NUMBER_REGEX
// optional "± [number]"
+ "(?:\\s*(?:±|\\+-)\\s*" + NUMBER_REGEX + ")?");
-
+
/**
* Gets an UncertainDouble from a double string. The uncertainty of the
* double will be one of the lowest decimal place of the number. For example,
* "12345.678" will become 12345.678 ± 0.001.
*
+ * @param s string to parse
+ * @return parsed {@code UncertainDouble}
+ *
* @throws NumberFormatException if the argument is not a number
*
* @since 2022-04-18
@@ -59,10 +62,11 @@ public final class UncertainDouble implements Comparable<UncertainDouble> {
final double uncertainty = Math.pow(10, -value.scale());
return UncertainDouble.of(value.doubleValue(), uncertainty);
}
-
+
/**
- * Parses a string in the form of {@link UncertainDouble#toString(boolean, RoundingMode)}
- * and returns the corresponding {@code UncertainDouble} instance.
+ * Parses a string in the form of
+ * {@link UncertainDouble#toString(boolean, RoundingMode)} and returns the
+ * corresponding {@code UncertainDouble} instance.
* <p>
* This method allows some alternative forms of the string representation,
* such as using "+-" instead of "±".
@@ -75,11 +79,11 @@ public final class UncertainDouble implements Comparable<UncertainDouble> {
public static final UncertainDouble fromString(String s) {
Objects.requireNonNull(s, "s may not be null");
final Matcher matcher = TO_STRING.matcher(s);
-
+
if (!matcher.matches())
throw new IllegalArgumentException(
"Could not parse string \"" + s + "\".");
-
+
double value, uncertainty;
try {
value = Double.parseDouble(matcher.group(1));
@@ -87,7 +91,7 @@ public final class UncertainDouble implements Comparable<UncertainDouble> {
throw new IllegalArgumentException(
"String " + s + " not in correct format.");
}
-
+
final String uncertaintyString = matcher.group(2);
if (uncertaintyString == null) {
uncertainty = 0;
@@ -99,35 +103,45 @@ public final class UncertainDouble implements Comparable<UncertainDouble> {
"String " + s + " not in correct format.");
}
}
-
+
return UncertainDouble.of(value, uncertainty);
}
-
+
/**
* Gets an {@code UncertainDouble} from its value and <b>absolute</b>
* uncertainty.
*
+ * @param value double's value
+ * @param uncertainty double's uncertainty (non-negative)
+ * @return {@code UncertainDouble} instance with these parameters
+ *
* @since 2020-09-07
*/
public static final UncertainDouble of(double value, double uncertainty) {
return new UncertainDouble(value, uncertainty);
}
-
+
/**
* Gets an {@code UncertainDouble} from its value and <b>relative</b>
* uncertainty.
*
+ * @param value double's value
+ * @param relativeUncertainty double's uncertainty (non-negative); the
+ * absolute uncertainty is equal to this value
+ * multiplied by {@code relativeUncertainty}
+ * @return {@code UncertainDouble} instance with these parameters
+ *
* @since 2020-09-07
*/
public static final UncertainDouble ofRelative(double value,
double relativeUncertainty) {
return new UncertainDouble(value, value * relativeUncertainty);
}
-
+
private final double value;
-
+
private final double uncertainty;
-
+
/**
* @param value
* @param uncertainty
@@ -138,7 +152,7 @@ public final class UncertainDouble implements Comparable<UncertainDouble> {
// uncertainty should only ever be positive
this.uncertainty = Math.abs(uncertainty);
}
-
+
/**
* Compares this {@code UncertainDouble} with another
* {@code UncertainDouble}.
@@ -156,10 +170,13 @@ public final class UncertainDouble implements Comparable<UncertainDouble> {
public final int compareTo(UncertainDouble o) {
return Double.compare(this.value, o.value);
}
-
+
/**
* Returns the quotient of {@code this} and {@code other}.
*
+ * @param other number to divide by
+ * @return quotient
+ *
* @since 2020-09-07
*/
public final UncertainDouble dividedBy(UncertainDouble other) {
@@ -167,16 +184,19 @@ public final class UncertainDouble implements Comparable<UncertainDouble> {
return UncertainDouble.ofRelative(this.value / other.value, Math
.hypot(this.relativeUncertainty(), other.relativeUncertainty()));
}
-
+
/**
* Returns the quotient of {@code this} and the exact value {@code other}.
*
+ * @param other number to divide by
+ * @return quotient
+ *
* @since 2020-09-07
*/
public final UncertainDouble dividedByExact(double other) {
return UncertainDouble.of(this.value / other, this.uncertainty / other);
}
-
+
@Override
public final boolean equals(Object obj) {
if (this == obj)
@@ -190,7 +210,7 @@ public final class UncertainDouble implements Comparable<UncertainDouble> {
return false;
return true;
}
-
+
/**
* @param other another {@code UncertainDouble}
* @return true iff this and {@code other} are within each other's
@@ -202,7 +222,7 @@ public final class UncertainDouble implements Comparable<UncertainDouble> {
return Math.abs(this.value - other.value) <= Math.min(this.uncertainty,
other.uncertainty);
}
-
+
/**
* Gets the preferred scale for rounding a value for toString.
*
@@ -217,19 +237,19 @@ public final class UncertainDouble implements Comparable<UncertainDouble> {
// the value is rounded to the same number of decimal places as the
// uncertainty.
final BigDecimal bigUncertainty = BigDecimal.valueOf(this.uncertainty);
-
+
// the scale that will give the uncertainty two decimal places
final int twoDecimalPlacesScale = bigUncertainty.scale()
- bigUncertainty.precision() + 2;
final BigDecimal roundedUncertainty = bigUncertainty
.setScale(twoDecimalPlacesScale, RoundingMode.HALF_EVEN);
-
+
if (roundedUncertainty.unscaledValue().intValue() >= 20)
return twoDecimalPlacesScale - 1; // one decimal place
else
return twoDecimalPlacesScale;
}
-
+
@Override
public final int hashCode() {
final int prime = 31;
@@ -238,7 +258,7 @@ public final class UncertainDouble implements Comparable<UncertainDouble> {
result = prime * result + Double.hashCode(this.uncertainty);
return result;
}
-
+
/**
* @return true iff the value has no uncertainty
*
@@ -247,10 +267,13 @@ public final class UncertainDouble implements Comparable<UncertainDouble> {
public final boolean isExact() {
return this.uncertainty == 0;
}
-
+
/**
* Returns the difference of {@code this} and {@code other}.
*
+ * @param other number to subtract
+ * @return result of subtraction
+ *
* @since 2020-09-07
*/
public final UncertainDouble minus(UncertainDouble other) {
@@ -258,19 +281,25 @@ public final class UncertainDouble implements Comparable<UncertainDouble> {
return UncertainDouble.of(this.value - other.value,
Math.hypot(this.uncertainty, other.uncertainty));
}
-
+
/**
* Returns the difference of {@code this} and the exact value {@code other}.
*
+ * @param other number to subtract
+ * @return result of subtraction
+ *
* @since 2020-09-07
*/
public final UncertainDouble minusExact(double other) {
return UncertainDouble.of(this.value - other, this.uncertainty);
}
-
+
/**
* Returns the sum of {@code this} and {@code other}.
*
+ * @param other number to add
+ * @return result of addition
+ *
* @since 2020-09-07
*/
public final UncertainDouble plus(UncertainDouble other) {
@@ -278,16 +307,19 @@ public final class UncertainDouble implements Comparable<UncertainDouble> {
return UncertainDouble.of(this.value + other.value,
Math.hypot(this.uncertainty, other.uncertainty));
}
-
+
/**
* Returns the sum of {@code this} and the exact value {@code other}.
*
+ * @param other number to add
+ * @return result of addition
+ *
* @since 2020-09-07
*/
public final UncertainDouble plusExact(double other) {
return UncertainDouble.of(this.value + other, this.uncertainty);
}
-
+
/**
* @return relative uncertainty
* @since 2020-09-07
@@ -295,10 +327,13 @@ public final class UncertainDouble implements Comparable<UncertainDouble> {
public final double relativeUncertainty() {
return this.uncertainty / this.value;
}
-
+
/**
* Returns the product of {@code this} and {@code other}.
*
+ * @param other number to multiply
+ * @return product
+ *
* @since 2020-09-07
*/
public final UncertainDouble times(UncertainDouble other) {
@@ -306,49 +341,58 @@ public final class UncertainDouble implements Comparable<UncertainDouble> {
return UncertainDouble.ofRelative(this.value * other.value, Math
.hypot(this.relativeUncertainty(), other.relativeUncertainty()));
}
-
+
/**
* Returns the product of {@code this} and the exact value {@code other}.
*
+ * @param other number to multiply
+ * @return product
+ *
* @since 2020-09-07
*/
public final UncertainDouble timesExact(double other) {
return UncertainDouble.of(this.value * other, this.uncertainty * other);
}
-
+
/**
* Returns the result of {@code this} raised to the exponent {@code other}.
*
+ * @param other exponent
+ * @return result of exponentation
+ *
* @since 2020-09-07
*/
public final UncertainDouble toExponent(UncertainDouble other) {
Objects.requireNonNull(other, "other may not be null");
-
+
final double result = Math.pow(this.value, other.value);
final double relativeUncertainty = Math.hypot(
other.value * this.relativeUncertainty(),
Math.log(this.value) * other.uncertainty);
-
+
return UncertainDouble.ofRelative(result, relativeUncertainty);
}
-
+
/**
* Returns the result of {@code this} raised the exact exponent
* {@code other}.
*
+ * @param other exponent
+ * @return result of exponentation
+ *
* @since 2020-09-07
*/
public final UncertainDouble toExponentExact(double other) {
return UncertainDouble.ofRelative(Math.pow(this.value, other),
this.relativeUncertainty() * other);
}
-
+
/**
* Returns a string representation of this {@code UncertainDouble}.
* <p>
- * This method returns the same value as {@link #toString(boolean, RoundingMode)},
- * but {@code showUncertainty} is true if and only if the uncertainty is
- * non-zero.
+ * This method returns the same value as
+ * {@link #toString(boolean, RoundingMode)}, but {@code showUncertainty} is
+ * true if and only if the uncertainty is non-zero.
*
* <p>
* Examples:
@@ -365,7 +409,7 @@ public final class UncertainDouble implements Comparable<UncertainDouble> {
public final String toString() {
return this.toString(!this.isExact(), RoundingMode.HALF_EVEN);
}
-
+
/**
* Returns a string representation of this {@code UncertainDouble}.
* <p>
@@ -392,36 +436,40 @@ public final class UncertainDouble implements Comparable<UncertainDouble> {
* UncertainDouble.of(-5.01, 0).toString(true) = "-5.01 ± 0.0"
* </pre>
*
+ * @param showUncertainty uncertainty is only shown if this parameter is true
+ * @param roundingMode how to round values
+ * @return string representation of this {@code UncertainDouble}
+ *
* @since 2020-09-07
*/
public final String toString(boolean showUncertainty,
RoundingMode roundingMode) {
String valueString, uncertaintyString;
-
+
// generate the string representation of value and uncertainty
if (this.isExact()) {
uncertaintyString = "0.0";
valueString = Double.toString(this.value);
-
+
} else {
// round the value and uncertainty according to getDisplayScale()
final BigDecimal bigValue = BigDecimal.valueOf(this.value);
final BigDecimal bigUncertainty = BigDecimal.valueOf(this.uncertainty);
-
+
final int displayScale = this.getDisplayScale();
final BigDecimal roundedUncertainty = bigUncertainty
.setScale(displayScale, roundingMode);
final BigDecimal roundedValue = bigValue.setScale(displayScale,
roundingMode);
-
+
valueString = roundedValue.toString();
uncertaintyString = roundedUncertainty.toString();
}
-
+
// return "value" or "value ± uncertainty" depending on showUncertainty
return valueString + (showUncertainty ? " ± " + uncertaintyString : "");
}
-
+
/**
* @return absolute uncertainty
* @since 2020-09-07
@@ -429,7 +477,7 @@ public final class UncertainDouble implements Comparable<UncertainDouble> {
public final double uncertainty() {
return this.uncertainty;
}
-
+
/**
* @return value without uncertainty
* @since 2020-09-07