Provides support for physical quantities, automatic error calculation (including numeric errors), and dimension-checking done in the form of class-type checking.
This package contains more than 40 predefined quantities with
specific methods (e.g. Angle.sin(), Scalar.log())
and constants (e.g. Velocity.SPEED_OF_LIGHT, Mass.PROTON, Constant.µ0).
The appropriate quantity sub-class is automatically instantiated when needed.
Quantity classes support derivation, making the framework easily extendable. For example:
// Derives from top Quantity class.
public class MagneticDipoleMoment extends Quantity {
private final static Factory FACTORY = new Factory(SI.AMPERE.multiply(SI.METER.pow(2))) {
protected Quantity create() {
return new MagneticDipoleMoment();
}
};
}
// Derives from quantities other than the Quantity class.
public class Altitude extends Length {
private final static Factory FACTORY = new Factory(SI.METER.alternate("meter_height")) {
protected Quantity create() {
return new Altitude();
}
};
};
Note: Mapping of the predefined quantities occurs when the library is initialized
(Ref. {@link com.dautelle.JADE#initialize}). If the framework is
extended (e.g. new quantity sub-classes) the application has to make sure that
the new classes are initialized to ensure proper unit registration.
Quantities take into account measurement errors as well as numeric errors! This can be illustrated with the following example:
double x = 10864;
double y = 18817;
double z = 9 * Math.pow(x, 4)- Math.pow(y, 4) + 2 * Math.pow(y, 2);
System.out.println("Result using double : " + z);
> Result using double : 2.0
The mathematically correct value is z=1. However, Java compilers
using ANSI/IEEE double precision numbers evaluate z=2. Not even the first
digit is correct! This is due to a rounding error occurring when subtracting
two nearly equal floating point numbers. Now, lets write the same formula
using our physical quantities:
Scalar x = Scalar.valueOf(10864);
Scalar y = Scalar.valueOf(18817);
Scalar z = (Scalar) x.pow(4).multiply(9).subtract(y.pow(4)).add(y.pow(2).multiply(2));
System.out.println("Result using physical quantities : " + z.doubleValue());
System.out.println("Absolute error : " + z.getAbsoluteError());
> Result using physical quantities : 2.0
> Absolute error : 48.000000357627876
The same result is returned, but now you know you cannot trust it!
Quantities are displayed with the error on the last digit. This point can be illustrated with the following code:
Length x = (Length) Quantity.valueOf(1, SI.METER);
Velocity v = (Velocity) Quantity.valueOf(0.01, SI.METER.divide(SI.SECOND));
Duration t = (Duration) Quantity.valueOf(1, SI.MICRO(SI.SECOND));
for (int i=0; i < 10000000; i++) {
x = (Length) x.add(v.multiply(t));
}
System.out.println(x);
> 1.10000000 m
The exact value is guaranteed to be in the range:
[1.09999999 m, 1.10000001 m] .
The same calculation using double would have printed
> 1.099999999392253
with no idea on the accuracy of this result. The system unit of a quantity determinates its class.
For example, Quantity.valueOf("1 µm") and Quantity.valueOf("1.2 ft")
return a Length instance (both "µm" and "ft" units
are derived from SI.METER).
Multiple physical models are supported (e.g. Standard,
Relativistic, High-Energy, Quantum
and Natural). The current model defines the conversions being allowed
as well as the default units to output quantities. For example:
final Quantity x = Length.valueOf(1, NonSI.INCH);
System.out.println(x); // Default standard model, length are stated in meters.
LocalContext.execute(new Runnable() {
public void run() {
RelativisticModel.select(); // Selects the relativistic model.
System.out.println(x); // Lengths are stated in second.
Quantity y = x.add(Duration.valueOf("2.3 µs")); // Length and Duration can be added.
Mass m = Mass.massOf(Quantity.valueOf("12 GeV")); // Energy is compatible with mass (E=mc2)
}
});
> 2.540000000000000E-2 m
> 8.472528018033062E-11 s
Custom units for quantity output is allowed. For example:
Length x = (Length) Quantity.valueOf(123, SI.CENTI(SI.METER));
Length.showAs(NonSI.INCH); // Context-local.
System.out.println(x);
> 48.42519685039370 in