mutableCopy() {
return MutableMeasure.mutable(this);
}
/**
* Checks if this measure is near another measure of the same unit. Provide a variance threshold
* for use for a +/- scalar, such as 0.05 for +/- 5%.
*
*
* Inches.of(11).isNear(Inches.of(10), 0.1) // true
* Inches.of(12).isNear(Inches.of(10), 0.1) // false
*
*
* @param other the other measurement to compare against
* @param varianceThreshold the acceptable variance threshold, in terms of an acceptable +/- error
* range multiplier. Checking if a value is within 10% means a value of 0.1 should be passed;
* checking if a value is within 1% means a value of 0.01 should be passed, and so on.
* @return true if this unit is near the other measure, otherwise false
*/
default boolean isNear(Measure> other, double varianceThreshold) {
if (!this.unit().getBaseUnit().equivalent(other.unit().getBaseUnit())) {
return false; // Disjoint units, not compatible
}
// abs so negative inputs are calculated correctly
var tolerance = Math.abs(other.baseUnitMagnitude() * varianceThreshold);
return Math.abs(this.baseUnitMagnitude() - other.baseUnitMagnitude()) <= tolerance;
}
/**
* Checks if this measure is near another measure of the same unit, with a specified tolerance of
* the same unit.
*
*
* Meters.of(1).isNear(Meters.of(1.2), Millimeters.of(300)) // true
* Degrees.of(90).isNear(Rotations.of(0.5), Degrees.of(45)) // false
*
*
* @param other the other measure to compare against.
* @param tolerance the tolerance allowed in which the two measures are defined as near each
* other.
* @return true if this unit is near the other measure, otherwise false.
*/
default boolean isNear(Measure other, Measure tolerance) {
return Math.abs(this.baseUnitMagnitude() - other.baseUnitMagnitude())
<= Math.abs(tolerance.baseUnitMagnitude());
}
/**
* Checks if this measure is equivalent to another measure of the same unit.
*
* @param other the measure to compare to
* @return true if this measure is equivalent, false otherwise
*/
default boolean isEquivalent(Measure> other) {
if (!this.unit().getBaseUnit().equals(other.unit().getBaseUnit())) {
return false; // Disjoint units, not compatible
}
return Math.abs(baseUnitMagnitude() - other.baseUnitMagnitude()) <= EQUIVALENCE_THRESHOLD;
}
/** {@inheritDoc} */
@Override
default int compareTo(Measure o) {
return Double.compare(this.baseUnitMagnitude(), o.baseUnitMagnitude());
}
/**
* Checks if this measure is greater than another measure of the same unit.
*
* @param o the other measure to compare to
* @return true if this measure has a greater equivalent magnitude, false otherwise
*/
default boolean gt(Measure o) {
return compareTo(o) > 0;
}
/**
* Checks if this measure is greater than or equivalent to another measure of the same unit.
*
* @param o the other measure to compare to
* @return true if this measure has an equal or greater equivalent magnitude, false otherwise
*/
default boolean gte(Measure o) {
return compareTo(o) > 0 || isEquivalent(o);
}
/**
* Checks if this measure is less than another measure of the same unit.
*
* @param o the other measure to compare to
* @return true if this measure has a lesser equivalent magnitude, false otherwise
*/
default boolean lt(Measure o) {
return compareTo(o) < 0;
}
/**
* Checks if this measure is less than or equivalent to another measure of the same unit.
*
* @param o the other measure to compare to
* @return true if this measure has an equal or lesser equivalent magnitude, false otherwise
*/
default boolean lte(Measure o) {
return compareTo(o) < 0 || isEquivalent(o);
}
/**
* Returns the measure with the absolute value closest to positive infinity.
*
* @param the type of the units of the measures
* @param measures the set of measures to compare
* @return the measure with the greatest positive magnitude, or null if no measures were provided
*/
@SafeVarargs
static > Measure max(Measure... measures) {
if (measures.length == 0) {
return null; // nothing to compare
}
Measure max = null;
for (Measure measure : measures) {
if (max == null || measure.gt(max)) {
max = measure;
}
}
return max;
}
/**
* Returns the measure with the absolute value closest to negative infinity.
*
* @param the type of the units of the measures
* @param measures the set of measures to compare
* @return the measure with the greatest negative magnitude
*/
@SafeVarargs
static > Measure min(Measure... measures) {
if (measures.length == 0) {
return null; // nothing to compare
}
Measure max = null;
for (Measure measure : measures) {
if (max == null || measure.lt(max)) {
max = measure;
}
}
return max;
}
/**
* Returns a string representation of this measurement in a shorthand form. The symbol of the
* backing unit is used, rather than the full name, and the magnitude is represented in scientific
* notation.
*
* @return the short form representation of this measurement
*/
default String toShortString() {
// eg 1.234e+04 V/m (1234 Volt per Meter in long form)
return String.format("%.3e %s", magnitude(), unit().symbol());
}
/**
* Returns a string representation of this measurement in a longhand form. The name of the backing
* unit is used, rather than its symbol, and the magnitude is represented in a full string, not
* scientific notation. (Very large values may be represented in scientific notation, however)
*
* @return the long form representation of this measurement
*/
default String toLongString() {
// eg 1234 Volt per Meter (1.234e+04 V/m in short form)
return String.format("%s %s", magnitude(), unit().name());
}
}