## 3. Special Numeric Data Types

### 3.1. Positive and non-negative integers

Since it is common to have positive or non-negative integer attributes, it's preferable to use predefined datatypes, like `PositiveInteger` and `NonNegativeInteger`, as their range in an information design model, instead of defining them with the range `Integer` and adding a corresponding interval constraint.

In a (JavaScript or Java) model class definition, these attributes have to be implemented as integer-valued attributes with an interval constraint. It is, however, desirable to have built-in support for them, like in the data/document format definition language XML Schema.

### 3.2. The unit interval

Certain attributes, e.g., when representing probabilities, have the unit interval [0,1], or one of its open variants, as their range. They can be implemented as decimal-valued attributes with an interval constraint. But having a corresponding predefined datatype, like `UnitInterval`, is preferable.

### 3.3. Percentages

The values of certain attributes represent percentages, which are decimal numbers that have to be divided by 100 for obtaining the numeric value represented by them. In a user interface, the value of a percentage attribute is shown with a % suffix, similar to quantity attributes shown with a unit suffix. For supporting percentage attributes, a special predefined datatype like `Percent` is needed.

### 3.4. Arbitrary precision numbers

In widely used programming languages, like JavaScript and Java, the built-in standard datatypes for dealing with decimal numbers (like `number` in JavaScript and `double` in Java) do not support precise calculations. For instance, in JavaScript, the result of computing the subtraction 0.3 - 0.1 is not 0.2, but rather 0.09999999999999998, which is close to, but not the same as the correct result. Even if such a precision error may be acceptable in a use case like in physics simulation for games, it is not acceptable in a use case like financial accounting.

The concept of arbitrary-precision numbers is to allow calculations where the precision is only limited by the available computer memory, unlike the fixed-precision arithmetic implemented in a computer's arithmetic logic unit, which is normally employed by the standard arithmetic implementation of a programming language. Arbitrary-precision numbers are used in applications where precise results of calculations (even with large numbers) are required and where the calculation speed is not a critical factor.

In JavaScript, we can use a library like big.js or mathjs for arbitrary-precision calculations. For instance, using the big.js library, the precise result of the subtraction 0.3 - 0.1 is obtained in the following way:

```var x = new Big( 0.3);
var result = x.minus( 0.1);
console.log( result);  // 0.2```

The maximum number of decimal places and the rounding mode used to round the results of the critical operations `div`, `sqrt` and `pow` (with negative exponent) is determined by the value of the static properties `DP` and `RM` of the `Big` class, as illustrated by the following example:

```Big.DP = 10  // decimal places
Big.RM = 1   // default rounding mode

x = new Big( 2);
y = new Big( 3);
z = x.div( y)     // "0.6666666667"
z.sqrt()          // "0.8164965809"
z.pow(-3)         // "3.3749999995"```

The rounding mode property values 0..3 have the following meaning:

ValueDescriptionJava BigDecimal equivalent
0Rounds towards zero. I.e. truncate, no rounding.ROUND_DOWN
1Rounds towards nearest neighbour. If equidistant, rounds away from zero.ROUND_HALF_UP
2Rounds towards nearest neighbour. If equidistant, rounds towards even neighbour.ROUND_HALF_EVEN
3Rounds away from zero.ROUND_UP

In Java, we can use the built-in datatype class `BigDecimal` for arbitrary-precision calculations. For instance, the precise result of the subtraction 0.3 - 0.1 is obtained in the following way:

```import java.math.BigDecimal;
BigDecimal x = new BigDecimal("0.3");
BigDecimal y = new BigDecimal("0.2");
BigDecimal result = x.subtract( y);```

The maximum number of decimal places, called scale in Java, is either set implicitly by the constructor argument or explicitly with

`x.setScale( 2);`

A scale and rounding mode can be set for each operation by providing either a scale value and a `RoundingMode` enumeration literal or a `MathContext` object. They should be set at least for the critical operations `divide` and `pow` (with negative exponent), as illustrated by the following example:

```BigDecimal x = new BigDecimal("2");
BigDecimal y = new BigDecimal("3");
BigDecimal result = x.divide( y, 10, RoundingMode.ROUND_HALF_UP);```

In this example, the value of the `result` variable is 0.6666666667.