Home : Course Map : Chapter 10 : Java : Tech :
Arbitary Precision Number Types
JavaTech
Course Map
Chapter 10

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

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.