This blog was co-authored by:
Version 2.0 Released!
We are pleased to announce the release of Version 2.0 for the IBM Decimal Arithmetic Library for Java.
You can download it from Maven at Maven Central: com.ibm.jzos:decimal-arithmetic
See the License & Terms
1. What is the IBM Decimal Arithmetic Library?
The IBM Decimal Arithmetic Library for Java enables programmers to use decimal values and variables with extreme precision, as in languages such as COBOL and PL/I, which are known for their robust decimal arithmetic capabilities.
By utilizing this library, developers can ensure that their financial, monetary, or other precision-critical calculations are performed accurately and reliably, avoiding potential rounding errors that can occur with traditional binary floating-point representations.
As a result, Java applications can now handle complex financial transactions, statistical analysis, or other precision-sensitive tasks with the same level of precision as legacy systems written in COBOL or PL/I.
2. Product Features
2.1 Accurate Decimal Calculations
The IBM Decimal Arithmetic Library enables developers to accurately program applications that deal with decimal data, ensuring full compatibility with IBM COBOL on Z. The library helps avoid potential rounding errors that can occur with traditional binary floating-point representations.
2.2 Data Access Accelerator for High-Speed Z Performance
The IBM Decimal Arithmetic Library leverages the Data Access Accelerator (DAA), which uses the latest hardware decimal and vector-packed decimal instructions, to deliver accelerated performance on Z systems, ensuring high-performance decimal arithmetic operations.
2.3 Java-First Design
The library provides an idiomatic Java API, allowing developers to work with decimal arithmetic in a natural and familiar way, without a COBOL-like coding style.
3. How do I import it?
The recommended approach is to import the dependency via the Maven pom.xml file. You can do this by adding the following code block to your pom.xml:
<!-- Source: https://mvnrepository.com/artifact/com.ibm.jzos/decimal-arithmetic -->
<dependency>
<groupId>com.ibm.jzos</groupId>
<artifactId>decimal-arithmetic</artifactId>
<version>2.0.0</version>
<scope>compile</scope>
</dependency>
Alternatively, there are several other means of downloading the dependency, including downloading the JAR file directly from Maven Central.
4. Why use the Arithmetic Library? (Interest Computation Example)
To demonstrate the Arithmetic Library’s effectiveness, let’s consider an interest computation example. We’ll compare the results obtained using COBOL, Java BigDecimal, and the Java Arithmetic Library.
4.1 With COBOL
The original COBOL implementation of the interest computation example is as follows:
IDENTIFICATION DIVISION.
PROGRAM-ID. INTEREST.
DATA DIVISION.
WORKING-STORAGE SECTION.
* Inputs: B=Savings Balance, C=Annual Contribution, P=Interest rate, N=Number of years
01 B PIC 9 (15) V99 value 9638071955.02.
01 C PIC 9 (12) V99 value 1809459311.54.
01 P PIC V9(6) value .081090.
01 N PIC 999 value 30.
01 MN PIC 99V9 (6) .
* Pretty-printing formatters for B
01 BP PIC $*(14) 9.99.
01 BPC PIC $$$, $$$, $$$, $$$,$$9.99.
PROCEDURE DIVISION.
COMPUTE MN = (1 + P) ** N.
COMPUTE B = (B + C) * MN + C * ( (MN - 1) / P - 1) .
* Formatted print of final balance
MOVE B TO BP.
DISPLAY BP.
MOVE B TO BPC.
DISPLAY BPC.
GOBACK.
END PROGRAM INTEREST.
The output of this COBOL program is shown below, demonstrating the accurate result obtained using this legacy language.
COBOL output:
$***326047441749.26
⎵⎵⎵$326,047,441,749.26
4.2 With Java BigDecimal
In contrast, the Java implementation using BigDecimal is shown below, highlighting the challenges of achieving accurate decimal artithmetic with the generic java.math library.
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
public class InterestNoRoundingConst {
public static void main (String [] args) {
BigDecimal b = new BigDecimal (BigInteger.valueOf(963807195502L), 2);
BigDecimal c = new BigDecimal (BigInteger. valueOf(180945931154L), 2);
BigDecimal p = new BigDecimal (BigInteger.valueOf(81090), 6);
short n = 30;
// COMPUTE MN = (1 + P) ** N
BigDecimal mn = BigDecimal.ONE.add(p).pow (n);
// COMPUTE B = (B + C) * MN + C * ( (MN - 1) / P - 1) .
b = b.add(c) .multiply (mn) . add (
c.multiply (mn.subtract (BigDecimal.ONE) . divide (p, 20, RoundingMode.DOWN) . subtract (BigDecimal.ONE) ) ) ;
System.out.printf("$%17.2f\n",b);
System.out.println(new DecimalFormat("$#,##0.##") . format (b) ) ;
}
}
Notably, the output of this Java BigDecimal program differs from the COBOL result, yielding $326,047,467,304 instead of the correct $326,047,441,749.26.
BigDecimal output:
$⎵⎵326047467304.71
$326,047,467,304.71
This discrepancy underscores the limitations of using BigDecimal for certain precision-critical calculations, particularly when compared to the COBOL implementation.
4.3 With Java Arithmetic Library
To achieve the same level of accuracy as COBOL, we can utilize the IBM Decimal Arithmetic Library in our Java implementation, as shown below.
import com.ibm.arithmetic.decimal.DecimalPrecision;
import com.ibm.arithmetic.decimal.DecimalVariable;
import com.ibm.arithmetic.decimal.impl.generic.DAAPrecision;
import com.ibm.arithmetic.decimal.impl.daa. DAAFactory;
import com.ibm.arithmetic.decimal.impl.daa.DAADecimal;
public class TestInterestExample {
private static final DAAFactory df = new DAAFactory ();
public static void main (String [] args) throws Formatter. Exception {
DAAPrecision prec17s2 = new DAAPrecision (17, 2, true) ;
DAAPrecision prec8s6 = new DAAPrecision (8, 6, true) ;
DAAVariable b = df. createDecimalVariable (prec17s2, df.createDecimal (963807195502L, 2) ) ;
DAADecimal c = df.createDecimal (180945931154L, 2) ;
DAADecimal p = df.createDecimal (81090, 6);
DAADecimal n = df. createDecimal (30);
// COMPUTE MN = (1 + P) ** N
DAAVariable mn = df. createDecimalVariable (prec8s6, p.plus (1) . toThePowerOf (n) ) ;
// COMPUTE B = (B + C) * MN + C * ( (MN - 1) / P - 1) .
b. set (b.plus (c) . times (mn) . plus (c. times (mn.minus (1) .dividedBy (p) .minus (1) ) ) ) ;
System.out.println (b.format (Formatter. fromString("$*(14) 9.99") ));
System. out. println (b. format (Formatter. fromString ("$$$, $$$, $$$, $$$, $$9.99") ));
}
}
As demonstrated below, the Java Arithmetic Library produces the same accurate result as the original COBOL implementation, validating its effectiveness in handling precision-critical calculations.
Arithmetic library output:
$***326047441749.26
⎵⎵⎵$326,047,441,749.26
By using the Java Arithmetic Library, we can achieve the same level of accuracy as the COBOL implementation, overcoming the limitations of the Java BigDecimal class.
Let’s get started!
Download the IBM Decimal Arithmetic Library now and start building more accurate and reliable solutions.
Visit the Maven repository: Maven Central: com.ibm.jzos:decimal-arithmetic