Decimal-Java is a library to convert java.math.BigDecimal to and from IEEE-754r
Source: Hacker News
decimal-java
Decimal-java is a library to convert java.math.BigDecimal to and from IEEE‑754r (IEEE‑754‑2008) decimal byte representations.
Maven
Get decimal-java from Maven:
<dependency>
<groupId>org.firebirdsql</groupId>
<artifactId>decimal-java</artifactId>
<version>2.0.1</version>
</dependency>
Or use the coordinates:
org.firebirdsql
decimal-java
2.0.1
License
This library is licensed under the MIT license; see also LICENSE.md.
Status
The API is stable and is not expected to change.
- Version 2.0.0 and higher require Java 17 or higher and are modularized with module name
org.firebirdsql.decimal. - Version 1.0.2 requires Java 7 or higher and declares the automatic module name
org.firebirdsql.decimal.
Goals
The library provides conversion between java.math.BigDecimal and IEEE‑754r decimal formats. Specifically supported byte representations are:
decimal32decimal64decimal128
Other formats (arbitrary‑precision decimal) are not planned.
Non‑goals
The library does not include mathematical operations on decimal values. For arithmetic, use BigDecimal with MathContext.DECIMAL128, MathContext.DECIMAL64, or MathContext.DECIMAL32.
Usage
Full Javadoc (latest tagged release):
Decoding a Decimal32
byte[] bytes = {(byte) 0xc7, (byte) 0xf4, (byte) 0xd2, (byte) 0xe7};
Decimal32 decimal32 = Decimal32.parseBytes(bytes);
BigDecimal bigDecimal = decimal32.toBigDecimal();
assertEquals(new BigDecimal("-1.234567E+96"), bigDecimal);
toBigDecimal() throws DecimalInconvertibleException if the value is infinity or NaN; the exception contains the actual type and sign.
Encoding a Decimal32
BigDecimal bigDecimal = new BigDecimal("-7.50E-7");
Decimal32 decimal32 = Decimal32.valueOf(bigDecimal);
byte[] bytes = decimal32.toBytes();
assertArrayEquals(new byte[] {(byte) 0xa1, (byte) 0xc0, 0x03, (byte) 0xd0}, bytes);
Rounding is applied if the BigDecimal does not fit a Decimal32; overflow rounds to infinity. To reject overflow:
Decimal32 decimal32 = Decimal32.valueOf(bigDecimal, OverflowHandling.THROW_EXCEPTION);
byte[] bytes = decimal32.toBytes();
assertArrayEquals(new byte[] {(byte) 0xa1, (byte) 0xc0, 0x03, (byte) 0xd0}, bytes);
Conversion works similarly for Decimal64 and Decimal128.
Available valueOf overloads
BigDecimalBigInteger(includingvalueOfExact(BigInteger)which throwsDecimalOverflowExceptionon rounding)Stringdouble
The parent class Decimal (superclass of Decimal32, Decimal64, Decimal128) also provides conversion between decimal types.
Conversion methods
toBytes()toBigDecimal()– throwsDecimalInconvertibleExceptionfor infinity/NaNtoString()doubleValue()toDecimal(Class)andtoDecimal(Class, OverflowHandling)
To obtain a BigInteger, use toBigDecimal().toBigInteger(), noting that large values (especially Decimal128) may consume significant memory.
Background
Firebird 4.0 introduced the SQL DECFLOAT type (precision 16 and 34 digits) using decimal64 and decimal128 in the protocol. Jaybird, the Firebird JDBC driver, needed support for these formats. Since no suitable library was found, decimal-java was created and released as a separate project for broader use. Jaybird includes a copy of the library to avoid extra dependencies for non‑Maven/Gradle environments.
References
- General Decimal Arithmetic
- Decimal Arithmetic Encodings
- A Summary of Densely Packed Decimal encoding
- The decNumber Library
- Firebird 4.0 Release Notes
SPDX-License-Identifier: MIT