Home : Course Map : Chapter 10 : Java : Tech : Arbitary Precision Number Types
 Introduction Vector/Enumeration Hashtable,HashMap    Properties Collections Iterator/ArrayList Generics Preferences API   Demo 1 Concurrency Utils Enumerated Type Arrays Class String Tools   String   StringBuffer   StringBuilder   StringTokenizer   String.split() Calendar,Date,Time   Demo 2   Demo 3 Other Utilities Exercises
 Supplements Performance Benchmarks
 About JavaTech      Codes List      Exercises      Feedback      References      Resources      Tips      Topic Index      Course Guide      What's New

The 64 bits in the long type correspond to about 19 decimal digits. There are applications, however, that deal with numbers containing many more digits than provided by these types. For example, cryptography requires very large prime numbers, as many as 2000 bits are used, for the public/private key encryption algorithms.

Floating point values can represent large values but with limited precision. The double type contains a 53 bit signed significand, which translates to 15 to 17 digits decimal precision. As we discussed in Chapter 2, it is oftent the case that a finite fraction in decimal can not be represented by a finite number of digits in the binary base (such as 1/10). So there can be a loss of precision for a decimal value in floating point format. Techniques to minimize and quantify the accumulation of such errors over repeated calculations are available from error analysis methods. A brute force approach, however, is simply to use extremely high precision number representations that avoid the error build up altogether. Financial processing might use this approach, for example. Some mathematical exericises, such as calculating PI to higher and higher precision, require arbitrarily wide fractional values.

For such applications that require very large integer values and extremely precise decimal values, the package java.Math provides the BigInteger and BigDecimal classes. Instances of these classes hold values of arbitrary precision. The values internally are immutable. Like String objects, once created, they cannot change.

Since the object values are immutable, any operation on a value BigInteger or BigDecimal can only return a new value. This is something to consider when implementing algorithms with these classes that involve many operations. Unneeded values should be de-referenced so that the garbage collector can retrieve the memory space. Of course, operations with such classes will be much slower than those with primitive types.

In the following two sections we provide describe these two classes. See the Java 2 API Specifications, however, for details and descriptions of all the methods. See also reference Mak for a more extensive discussion of these classes and for code that provides additional mathematical operations.

### BigInteger

The BigInteger class contains methods that provide all the basic arithmetic operations such as add, subtract, multiply and divide. For example,

BigInteger bi1 = new BigInteger(“1143209523490543953412323238479”);
BigInteger bi2 = new BigInteger(“34548738754398454599999997876786578479”);
BigInteger bi3 = bi2.add(bi1);  // = bi2 + bi1
BigInteger bi4 = bi2.divide(bi1); // = bi2 / bi1

Note that bi3 and bi4 are new BigInteger objects created by the add() and divide() methods, respectively. There are four BigInteger instances in the four lines of code above. If bi1 and bi2 are no longer needed, they could be de-referenced as follows:

bi1 = bi2 = null;

With no more references to the BigInteger objects formerly known as bi1 and bi2, the garbage collector is free to reclaim that memory when needed.

Several other arithmetic methods are included in BigInteger as well, such as abs(), negate(), and pow(). Plus there are methods to return values as int, long, float, or double primitives. These are, of course, narrowing conversions that lose information about the value if the BigInteger value is too large to represent as the primitive type. See the API documentation for full details.

Since the BigInteger instances are mostly used for encryption tasks, there are several methods related to prime number generation and modulo arithmetic. This include

static BigInteger probablePrime(int numberBits, Random ran)

This method generates a number that has a high likelihood of being prime. The arguments include the bit length of the prime number and a reference to an instance of the Random class that the method will use to select candidates for primality. The method

boolean isProbablePrime(int certainity)

Here the certainty parameter indicates the desired level of confidence that the number really is prime. If the probability exceeds (1 -1/2certainty) , the method returns true.

The BigInteger class, see above, contains methods to carry out various bitwise operations. For example,

BigInteger shiftLeft(int n)
BigInteger shiftRight(int n)

These return new values shifted left or right by the number of bits indicated. Other bitwise methods include:  and, or, XOR, not, andNot, testBit, setBit, clearBit, and flipBit.

We note that BigInteger implements Comparable, which makes arrays of BigInteger objects sortable with the java.util.Arrays methods described in Chapter 10: Java : Arrays Class. and Chapter 8: Tech : Histogram Sorting. The compareTo() method, required by Comparable, is useful for comparing two BigInteger values outside of the sort() methods.

### BigDecimal

BigDecimal contains internally an arbitrary precision integer - unscaledValue - and a 32 bit scale value - scale. The value represented by a BigDecimal object corresponds to

unscaledValue / 10scale

So for this instance of BigDecimal

BigDecimal one = new BigDecimal(new BigInteger(“1”), Integer.MAX_VALUE);

the decimal point is 231-1 (2,147,483,648) places to the left of the 1.  You can obtain a new BigDecimal value with the scale increased by n places via the method

BigDecimal movePointLeft(int n)

Similarly, you can obtain a new value with the scale decreased by n places   using

BigDecimal movePointRight(int n)

Note that in both cases the precision of the unscaled value remains unchanged. Only the decimal point has moved.

Other methods provide the scale value (as an int) and the unscaled value (as an instance of BigInteger). There are also methods that return a float and a double type value, with the precision truncated as necessary to fit the narrower fractional range of these floating point types.

As with BigInteger, the BigDecimal class contains methods that provide all the basic arithmetic operations such as add, subtract, multiply and divide. However, for the division, one of eight rounding options must be chosen. For example,

BigDecimal bd1 = new BigDecimal(
new BigInteger(“1143209523490543953412323238479”,12345);
BigDecimal bd2 = new
BigDecimal(“3.4548738754398454599999997876786578479”);

// = bd2 / bd1
BigDecimal bd4 = bd2.divide(bd1, BigDecimal.ROUND_DOWN);

Here the division rounds towards zero. Other rounding style constants defined in the BigDecimal class include ROUND_UP, ROUND_FLOOR, ROUND_CEILING, etc. See the API documentation for rounding details.

References & Web Resources

• Robert Mak, Java Number Cruncher: The Java Programmer's Guide to Numerical Computing, 2003.
• Specifications:

Latest update: Nov. 19, 2004

 Tech ArbitaryPrecision    BigInteger    BigDecimal Bit Handling Exercises
 Physics Data Gen&Analysis   Demo 1   Demo 2 Exercises
 Part I Part II Part III Java Core 1  2  3  4  5  6  7  8  9  10  11  12 13 14 15 16 17 18 19 20 21 22 23 24 Supplements 1  2  3  4  5  6  7  8  9  10  11  12 Tech 1  2  3  4  5  6  7  8  9  10  11  12 Physics 1  2  3  4  5  6  7  8  9  10  11  12

Java is a trademark of Sun Microsystems, Inc.