# Introduction to JSR-275: Measures and Units

### New API specification removes uncertainty from programming with physical measurements

Page 3 of 4

For convenience, the `SI` class provides static multiplier methods, such as `KILO(Unit)` or `CENTI(Unit)`, equivalent to the multiplication or division of the unit by a power of 10. For example, `KILO(METER`) is equivalent to `METER.times(1000)`, whereas `CENTI(METER)` is equivalent to `METER.divide(100)`.

As Listing 7 shows, you can also create new units with a new symbol to distinguish between quantities of a different nature but of the same dimension (`AlternateUnit`) or by combining several units together (`CompoundUnit`). `CompoundUnit` is used exclusively for formatting purposes (see Parsing and formatting).

#### Listing 7. Creating new units and symbols

``` ```Unit<Angle> RADIAN = ONE.alternate("rad");
Unit<Pressure> PASCAL = NEWTON.divide(METER.pow(2)).alternate("Pa");
Unit<Duration> HOUR_MINUTE_SECOND = HOUR.compound(MINUTE).compound(SECOND);
Unit<Angle> DEGREE_MINUTE_ANGLE = DEGREE_ANGLE.compound(MINUTE_ANGLE);```
```

Figure 1 shows a UML diagram of the unit package.

Given two units of same dimensions, you can retrieve the `UnitConverter` between the two units. Then you can use the converter to perform conversions of `double` values, as shown in Listing 8.

#### Listing 8. Converting `double` values with `UnitConverter`

``` ```double distanceInMiles = 23.0;
UnitConverter mileToKilometer = MILE.getConverterTo(KILO(METER));
double distanceInKilometers = mileToKilometer.convert(distanceInMiles);```
```

For more complex numeric types such as `BigDecimal`, conversions are more elaborate and are performed by the `Measure` implementation directly. For example, the `Measure` implementation for `BigDecimal` takes into account the `MathContext` holding the precision and the rounding mode. It should be noted that most `UnitConverter`s between predefined units are instances of `RationalConverter` (the ratio of two integer numbers) and as such do not introduce conversion errors of their own. When you create new derived units, it's recommended that you use integer multipliers or divisors whenever possible instead of double-value multipliers. Often decimal numbers don't have an exact binary representation (IEE754 format for double), and units derived from such inexact numbers could introduce numeric error artifacts during conversions. Listing 9 shows a 128-bit conversion from meters to feet using `BigDecimal`.

#### Listing 9. BigDecimal conversion

``` ```Unit<Length> FOOT = METER.times(3048).divide(10000); // Exact.
BigDecimal meters = new BigDecimal("9192631770.03345677");
MathContext ctx = MathContext.DECIMAL128;
Measure<BigDecimal, Length> m = Measure.valueOf(meters, METER, ctx);
BigDecimal feet = m.to(FOOT).getValue();```
```

The numeric value for `Measure` does not need to be a scalar. It can be an array, for example, in which case the conversion of the whole array can be performed with a single operation (which is also efficient, because the converter is calculated only once). Listing 10 shows the conversion of a velocity vector.

#### Listing 10. Vector conversion

``` ```Measure<double[], Velocity> velocity3D
= Measure.valueOf(new double[] { 0.2, -0.3, 0.5 }, METER_PER_SECOND);
double[] milesPerHour = velocity3D.to(MILE.divide(HOUR)).getValue();```
```

## Unit converters

Unit converters have two purposes: converting between units and creating new derived units (`TransformedUnit`).

Most users don't need to instantiate `UnitConverter`, because convenience methods such as `Unit.times(double)` or `Unit.divide(long)` do this for you. The predefined converters in the converter package (shown in Figure 2) should be sufficient for most applications. However, you can create custom converters. For example, embedded systems might use a device-specific converter whose value changes with temperature. It is safe for an application to work with the device units (not corrected) and/or the standard units (corrected). Measures stated in both units cannot be confused or mixed without explicit conversions.

## Parsing and formatting

`Unit` and `Measure` parsing and formatting follow the standard Java paradigm for formatting locale-sensitive information such as dates, messages and numbers. (A `Locale` object represents a specific geographical, political or cultural region. An operation that requires a `Locale` to perform its task is called locale-sensitive and uses the `Locale` to tailor information for the user.) Two abstract classes derived from `java.util.Format` -- `UnitFormat` and `MeasureFormat` -- provide the locale-sensitive instances as well as locale-insensitive instances to facilitate unambiguous electronic communication of quantities together with their units (UCUM format). The default format used by the `Unit.toString()` and `Unit.valueOf(String)` methods is locale-sensitive and should not be used to send information over the Atlantic; otherwise a measure such as `1.0 Gal` (about 3.78 liters in the United States) would be interpreted as about 4.54 liters in the United Kingdom (1 UK gallon)!

| Page 3
``` ```