diff options
| author | Adrien Hopkins <ahopk127@my.yorku.ca> | 2021-05-22 14:05:44 -0500 | 
|---|---|---|
| committer | Adrien Hopkins <ahopk127@my.yorku.ca> | 2021-05-22 14:05:44 -0500 | 
| commit | 8645325803f8580c823cc4c2cec2ad76906b52bb (patch) | |
| tree | fff893611dfd82aca4af5e677ab782045d5543d9 /src/org/unitConverter/math/UncertainDouble.java | |
| parent | 184b7cc697ffc2dcbd49cfb3d0fd7b14bdac8803 (diff) | |
| parent | 277500e27010839e03659870bc5890f1535aa8c8 (diff) | |
Merge branch 'develop' into feature-settings-tab
Diffstat (limited to 'src/org/unitConverter/math/UncertainDouble.java')
| -rw-r--r-- | src/org/unitConverter/math/UncertainDouble.java | 419 | 
1 files changed, 0 insertions, 419 deletions
| diff --git a/src/org/unitConverter/math/UncertainDouble.java b/src/org/unitConverter/math/UncertainDouble.java deleted file mode 100644 index 3651bd5..0000000 --- a/src/org/unitConverter/math/UncertainDouble.java +++ /dev/null @@ -1,419 +0,0 @@ -/** - * Copyright (C) 2020 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program.  If not, see <https://www.gnu.org/licenses/>. - */ -package org.unitConverter.math; - -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.util.Objects; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * A double with an associated uncertainty value. For example, 3.2 ± 0.2. - * <p> - * All methods in this class throw a NullPointerException if any of their - * arguments is null. - * - * @since 2020-09-07 - */ -public final class UncertainDouble implements Comparable<UncertainDouble> { -	/** -	 * The exact value 0 -	 */ -	public static final UncertainDouble ZERO = UncertainDouble.of(0, 0); -	 -	/** -	 * 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\\.\\,]+))?"); -	 -	/** -	 * Parses a string in the form of {@link UncertainDouble#toString(boolean)} -	 * and returns the corresponding {@code UncertainDouble} instance. -	 * <p> -	 * This method allows some alternative forms of the string representation, -	 * such as using "+-" instead of "±". -	 *  -	 * @param s string to parse -	 * @return {@code UncertainDouble} instance -	 * @throws IllegalArgumentException if the string is invalid -	 * @since 2020-09-07 -	 */ -	public static final UncertainDouble fromString(String s) { -		Objects.requireNonNull(s, "s may not be null"); -		final Matcher matcher = TO_STRING.matcher(s); -		 -		double value, uncertainty; -		try { -			value = Double.parseDouble(matcher.group(1)); -		} catch (IllegalStateException | NumberFormatException e) { -			throw new IllegalArgumentException( -					"String " + s + " not in correct format."); -		} -		 -		final String uncertaintyString = matcher.group(2); -		if (uncertaintyString == null) { -			uncertainty = 0; -		} else { -			try { -				uncertainty = Double.parseDouble(uncertaintyString); -			} catch (final NumberFormatException e) { -				throw new IllegalArgumentException( -						"String " + s + " not in correct format."); -			} -		} -		 -		return UncertainDouble.of(value, uncertainty); -	} -	 -	/** -	 * Gets an {@code UncertainDouble} from its value and <b>absolute</b> -	 * uncertainty. -	 *  -	 * @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. -	 *  -	 * @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 -	 * @since 2020-09-07 -	 */ -	private UncertainDouble(double value, double uncertainty) { -		this.value = value; -		// uncertainty should only ever be positive -		this.uncertainty = Math.abs(uncertainty); -	} -	 -	/** -	 * Compares this {@code UncertainDouble} with another -	 * {@code UncertainDouble}. -	 * <p> -	 * This method only compares the values, not the uncertainties. So 3.1 ± 0.5 -	 * is considered less than 3.2 ± 0.5, even though they are equivalent. -	 * <p> -	 * <b>Note:</b> The natural ordering of this class is inconsistent with -	 * equals. Specifically, if two {@code UncertainDouble} instances {@code a} -	 * and {@code b} have the same value but different uncertainties, -	 * {@code a.compareTo(b)} will return 0 but {@code a.equals(b)} will return -	 * {@code false}. -	 */ -	@Override -	public final int compareTo(UncertainDouble o) { -		return Double.compare(this.value, o.value); -	} -	 -	/** -	 * Returns the quotient of {@code this} and {@code other}. -	 *  -	 * @since 2020-09-07 -	 */ -	public final UncertainDouble dividedBy(UncertainDouble other) { -		Objects.requireNonNull(other, "other may not be null"); -		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}. -	 *  -	 * @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) -			return true; -		if (!(obj instanceof UncertainDouble)) -			return false; -		final UncertainDouble other = (UncertainDouble) obj; -		if (Double.compare(this.value, other.value) != 0) -			return false; -		if (Double.compare(this.uncertainty, other.uncertainty) != 0) -			return false; -		return true; -	} -	 -	/** -	 * @param other another {@code UncertainDouble} -	 * @return true iff this and {@code other} are within each other's -	 *         uncertainty range. -	 * @since 2020-09-07 -	 */ -	public final boolean equivalent(UncertainDouble other) { -		Objects.requireNonNull(other, "other may not be null"); -		return Math.abs(this.value - other.value) <= Math.min(this.uncertainty, -				other.uncertainty); -	} -	 -	/** -	 * Gets the preferred scale for rounding a value for toString. -	 *  -	 * @since 2020-09-07 -	 */ -	private final int getDisplayScale() { -		// round based on uncertainty -		// if uncertainty starts with 1 (ignoring zeroes and the decimal -		// point), rounds -		// so that uncertainty has 2 significant digits. -		// otherwise, rounds so that uncertainty has 1 significant digits. -		// 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; -		int result = 1; -		result = prime * result + Double.hashCode(this.value); -		result = prime * result + Double.hashCode(this.uncertainty); -		return result; -	} -	 -	/** -	 * @return true iff the value has no uncertainty -	 *  -	 * @since 2020-09-07 -	 */ -	public final boolean isExact() { -		return this.uncertainty == 0; -	} -	 -	/** -	 * Returns the difference of {@code this} and {@code other}. -	 *  -	 * @since 2020-09-07 -	 */ -	public final UncertainDouble minus(UncertainDouble other) { -		Objects.requireNonNull(other, "other may not be null"); -		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}. -	 *  -	 * @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}. -	 *  -	 * @since 2020-09-07 -	 */ -	public final UncertainDouble plus(UncertainDouble other) { -		Objects.requireNonNull(other, "other may not be null"); -		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}. -	 *  -	 * @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 -	 */ -	public final double relativeUncertainty() { -		return this.uncertainty / this.value; -	} -	 -	/** -	 * Returns the product of {@code this} and {@code other}. -	 *  -	 * @since 2020-09-07 -	 */ -	public final UncertainDouble times(UncertainDouble other) { -		Objects.requireNonNull(other, "other may not be null"); -		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}. -	 *  -	 * @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}. -	 *  -	 * @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}. -	 *  -	 * @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)}, but -	 * {@code showUncertainty} is true if and only if the uncertainty is -	 * non-zero. -	 *  -	 * <p> -	 * Examples: -	 *  -	 * <pre> -	 * UncertainDouble.of(3.27, 0.22).toString() = "3.3 ± 0.2" -	 * UncertainDouble.of(3.27, 0.13).toString() = "3.27 ± 0.13" -	 * UncertainDouble.of(-5.01, 0).toString() = "-5.01" -	 * </pre> -	 *  -	 * @since 2020-09-07 -	 */ -	@Override -	public final String toString() { -		return this.toString(!this.isExact()); -	} -	 -	/** -	 * Returns a string representation of this {@code UncertainDouble}. -	 * <p> -	 * If {@code showUncertainty} is true, the string will be of the form "VALUE -	 * ± UNCERTAINTY", and if it is false the string will be of the form "VALUE" -	 * <p> -	 * VALUE represents a string representation of this {@code UncertainDouble}'s -	 * value. If the uncertainty is non-zero, the string will be rounded to the -	 * same precision as the uncertainty, otherwise it will not be rounded. The -	 * string is still rounded if {@code showUncertainty} is false.<br> -	 * UNCERTAINTY represents a string representation of this -	 * {@code UncertainDouble}'s uncertainty. If the uncertainty ends in 1X -	 * (where X represents any digit) it will be rounded to two significant -	 * digits otherwise it will be rounded to one significant digit. -	 * <p> -	 * Examples: -	 *  -	 * <pre> -	 * UncertainDouble.of(3.27, 0.22).toString(false) = "3.3" -	 * UncertainDouble.of(3.27, 0.22).toString(true) = "3.3 ± 0.2" -	 * UncertainDouble.of(3.27, 0.13).toString(false) = "3.27" -	 * UncertainDouble.of(3.27, 0.13).toString(true) = "3.27 ± 0.13" -	 * UncertainDouble.of(-5.01, 0).toString(false) = "-5.01" -	 * UncertainDouble.of(-5.01, 0).toString(true) = "-5.01 ± 0.0" -	 * </pre> -	 *  -	 * @since 2020-09-07 -	 */ -	public final String toString(boolean showUncertainty) { -		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.HALF_EVEN); -			final BigDecimal roundedValue = bigValue.setScale(displayScale, -					RoundingMode.HALF_EVEN); -			 -			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 -	 */ -	public final double uncertainty() { -		return this.uncertainty; -	} -	 -	/** -	 * @return value without uncertainty -	 * @since 2020-09-07 -	 */ -	public final double value() { -		return this.value; -	} -} | 
