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.