Decimal-Java is a library to convert java.math.BigDecimal to and from IEEE-754r

Published: (February 24, 2026 at 04:15 AM EST)
3 min read

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.

Java CI with Gradle
Maven Central

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:

  • decimal32
  • decimal64
  • decimal128

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

  • BigDecimal
  • BigInteger (including valueOfExact(BigInteger) which throws DecimalOverflowException on rounding)
  • String
  • double

The parent class Decimal (superclass of Decimal32, Decimal64, Decimal128) also provides conversion between decimal types.

Conversion methods

  • toBytes()
  • toBigDecimal() – throws DecimalInconvertibleException for infinity/NaN
  • toString()
  • doubleValue()
  • toDecimal(Class) and toDecimal(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

SPDX-License-Identifier: MIT

0 views
Back to Blog

Related posts

Read more »

store3

gradle task runQuantumtype: JavaExec { dependsOn prepareLibDir, classes systemProperty 'org.gradle.scan.acceptTerm', 'true' doFirst { setTmpDir buildFileSystem'...