# Decimal arithmetic for Java

The JavaTM runtime environment includes a class (java.math.BigDecimal) for decimal arithmetic. While suitable for simple financial calculations, it is missing a number of features that are necessary for general-purpose decimal arithmetic. This document describes what is missing, and proposes a small and upwards compatible enhancement to the BigDecimal class which makes the necessary additions.

Included in this document are:

• an overview of the proposal (this section)
• the concepts behind the design
• the description of the proposed classes
• a detailed definition of the arithmetic
• notes and change history.

#### The requirements

Java currently provides classes (java.math.BigDecimal and java.math.BigInteger) for fixed point arithmetic, and also supports native integer and binary floating point arithmetic directly. Binary floating point is usually implemented by hardware, and therefore is widely used for 'numerically intensive' work where performance is critical.

However, with the growth in importance of applications where usability is the primary concern, the anomalies of binary floating point arithmetic (such as the inability to represent common values such as 0.10 exactly) are increasingly troublesome.[1]  In financial and commercial applications, especially, an arithmetic which can achieve exact decimal results when required is essential. This is the original purpose of the BigDecimal class.

Unfortunately, the current BigDecimal class provides only a limited set of fixed point operations on numbers which are in practice limited to those which can be represented conveniently as 'plain' numbers, with no exponent. There are, in addition, a number of problems with conversions to and from other Java types. These, and the other problems with the BigDecimal class, are listed overleaf.

Problems with the BigDecimal class:

1. The fixed point (integer + scale) arithmetic is suitable for some tasks (such as calculating taxes or balancing a check book), but is inconvenient and awkward for many common applications.
For example, calculating the total amount repaid on a mortgage over 20 years is difficult, requiring several steps which do not involve exact arithmetic and which may require explicit rounding. For this task (and many others) an arithmetic that allows working to a chosen precision is both simpler and more convenient.
2. Several operators commonly used in applications are missing, specifically integer division, remainder, and exponentiation to an integer power (as required for straightforward calculation of the mortgage repayment just described, for example).
3. The constructors for BigDecimal do not accept exponential notation. This means that results from other sources (for example, spreadsheets and calculators, or the Java Double.toString() method) are difficult to use.
4. The string form of a BigDecimal is always a plain number. This means that very large or very small numbers are expressed using many digits -- this makes them expensive and difficult to handle. For many calculations an exponential or floating point representation is desirable (and is potentially more efficient).
5. The conversions from BigDecimal to Java integer types are dangerous. Specifically, they are treated as a narrowing primitive conversion, even though there is a change of base involved. This means that decimal parts of numbers can be dropped without warning, and high order significant bits can also be lost without warning (an error sometimes called 'decapitation'). It was exactly this kind of error that caused the loss of the Ariane 5 launcher in 1996.[2]

In the proposal that follows, these deficiencies are addressed by adding floating point arithmetic and exponential notation to the BigDecimal class, in a fully upwards-compatible and seamless manner. In addition, the set of base operators is completed, and new robust conversion methods are added.

#### The proposal

This proposal answers the primary requirements of the last section by adding support for decimal floating point arithmetic to the BigDecimal class. This is achieved by simply adding a second parameter to the existing operator methods. The augmented class implements the decimal arithmetic defined in the ANSI standard X3.274-1996,[3]  which has the following advantages:
• The arithmetic was designed as a full-function decimal floating point arithmetic, directly implementing the rules that people are taught at school.
For example, number length information is not lost, so trailing zeros can be correctly preserved in most operations: 1.20 times 2 gives 2.40, not 2.4. This behavior is essential both for usability and to maintain compatibility with the existing BigDecimal class.
• Being a true decimal arithmetic, exact results are given when expected (for instance, 0.9/10 gives 0.09, not 0.089999996).
• The precision of the arithmetic is freely selectable by the user, not limited to a choice from one or two alternatives; where necessary, calculations may be made using thousands of digits. The operator definitions, and current implementations, impose no upper limit on precision (though in practice, memory or processor constraints will bound some calculations).
• The arithmetic operations are robust; there is no 'wrap' of integers at certain sizes, and ill-defined or out-of-range results immediately throw exceptions.
• The concept of a context for operations is explicit. This allows application-global rules (such as precision and rounding) to be easily implemented and modified. This aids testing and error analysis, as well as simplifying programming.
• Integers and fixed-scale numbers are a proper subset of all numbers. Conversions to and from a different class are not necessary in order to carry out integer and currency calculations.
• A large range of numbers are supported; by definition, exponents in the range of at least E-999999999 through E+999999999 are supported, with a default precision of nine decimal digits. Both scientific (where one digit is shown before the decimal point) and engineering (where the power of ten is a multiple of three) exponential notations are supported.
• The arithmetic was developed over several years, based directly on user feedback and requirements, and in consultation with professional mathematicians and data processing experts. It has been heavily used for over 16 years without problems, and was recently reviewed in depth and ratified by the X3J18 committee for ANSI.
• Numerous public-domain and commercial implementations of the arithmetic exist. IBM has implementations in C, C++, various Assembler languages, and for Java.

This arithmetic has been further enhanced by supporting a variety of rounding algorithms, as already defined in Java 1.1 for the java.math.BigDecimal class.

A prototype of the proposed enhanced BigDecimal class has been specified (see the remainder of this document) and has been fully implemented, including javadoc comments following Java guidelines and an appropriate set of test cases.

It is a small class (at approximately 23,000 bytes, including line number tables, it is smaller than the BigInteger class in Java 1.2), and does not use any native methods. The class is based on code that has been in use since 1996, and which has been packaged as a BigDecimal class since June 1998. It has been available on the IBM alphaWorks site since late 1998.

For reasons explained later, the detail in this document also proposes adding one very small new context class to Java, in addition to enhancing the BigDecimal class. The new class would most logically be added to the java.math package in the Java Runtime Environment, and it is suggested that it be called MathContext.

The changes to the Java runtime proposed are summarized on the next page.

The changes to the current Java API affect only two classes; BigDecimal (which is enhanced from the current specification) and MathContext (which is new).

BigDecimal

Instantiates a decimal number, and includes:

1. Constructors and methods for creating a BigDecimal number from the primitive Java types, and from strings and BigInteger object. Four constructors and one method have been added.
2. Operator methods, for the usual arithmetic operators, including comparisons. Four new operators have been added, and all operator methods have a second version which specifies a context.
3. Other methods, including standard Java methods (equals, hashCode, etc.), and conversions to primitive types and String (intValueExact, floatValue, toString, format, signum, etc.). Seven methods have been added, mostly to effect robust (error-detecting) conversions.
This initial proposal does not include transcendental functions.

MathContext

A very small class, used for defining a context for arithmetic, as described in the next section. This comprises four constructors and five methods (four 'get' methods and a toString() method).

These classes are available for testing in the package com.ibm.math (that is, as the classes com.ibm.math.BigDecimal and com.ibm.math.MathContext). Comments on them and on this draft are welcome. Please send comments to Mike Cowlishaw, mfc@speleotrove.com.

#### Acknowledgements

Very many people have contributed to the arithmetic described in this document, especially the IBM REXX language committee, the IBM Vienna Compiler group, and the X3 (now NCITS) J18 technical committee. Special thanks for their contributions to the current design are due to Joshua Bloch, Dirk Bosmans, and Brian Marks.
Footnotes:
 [1] See, for example, Floating point issues, C. Sweeney, at: http://www.truebasic.com/tech08.html [2] See: http://www.esrin.esa.it/htdocs/tidc/Press/Press96/ariane5rep.html [3] American National Standard for Information Technology -- Programming Language REXX, X3.274-1996, American National Standards Institute, New York, 1996.

[contents | next]