Decimal-Java 是一个将 `java.math.BigDecimal` 转换为 IEEE-754r 格式,并从 IEEE-754r 格式转换回 `java.math.BigDecimal` 的库。
Decimal-Java is a library to convert java.math.BigDecimal to and from IEEE-754r

原始链接: https://github.com/FirebirdSQL/decimal-java

## Decimal-Java: 一个 BigDecimal 转换库 Decimal-java 是一个 Java 库,用于将 `java.math.BigDecimal` 值与 IEEE-754r 十进制字节表示形式(decimal32、decimal64 和 decimal128)之间进行转换。它的设计目的是为了促进与使用这些十进制格式的系统的互操作性,最初的需求源于在 Jaybird JDBC 驱动程序中支持 Firebird 的 DECFLOAT 类型。 该库提供将 `BigDecimal` 和 `BigInteger` 编码为十进制字节数组(`toBytes()`)以及将字节数组解码回 `BigDecimal`(`toBigDecimal()`)的方法。 溢出处理可以配置为抛出异常或返回无穷大。 2.0.0+ 版本需要 Java 17 并且是模块化的,而旧版本(最高到 1.0.2)支持 Java 7+。 API 稳定,并采用 MIT 许可。 对于十进制数的数学运算,建议使用带有 `MathContext`(DECIMAL32、64 或 128)的 `BigDecimal`。 在 Maven 上找到该库:`org.firebirdsql:decimal-java:2.0.1`,Javadoc 位于 [https://firebirdsql.github.io/decimal-java/javadoc/](https://firebirdsql.github.io/decimal-java/javadoc/)。

黑客新闻 新 | 过去 | 评论 | 提问 | 展示 | 招聘 | 提交 登录 Decimal-Java 是一个将 java.math.BigDecimal 转换为和从 IEEE-754r 的库 (github.com/firebirdsql) 4 分,由 mariuz 发表于 2 小时前 | 隐藏 | 过去 | 收藏 | 讨论 帮助 指南 | 常见问题 | 列表 | API | 安全 | 法律 | 申请 YC | 联系方式 搜索:
相关文章

原文

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 MavenCentral

Get decimal-java from Maven:

<dependency>
    <groupId>org.firebirdsql</groupId>
    <artifactId>decimal-java</artifactId>
    <version>2.0.1</version>
</dependency>

This library is licensed under the MIT license, see also LICENSE.md.

The API is stable and is not expected to change.

Version 2.0.0 and higher require Java 17 or higher and is 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.

This library provides conversion between java.math.BigDecimal and IEEE-754r decimal formats.

Specifically supported are byte representations of:

  • decimal32
  • decimal64
  • decimal128

Other formats (arbitrary precision decimal) are not planned to be supported.

This library explicitly does not include mathematical operations on decimal. As an alternative, consider using BigDecimal with MathContext.DECIMAL128, MathContext.DECIMAL64, or MathContext.DECIMAL32.

For full javadoc (of latest tagged release), see https://firebirdsql.github.io/decimal-java/javadoc/

Decoding a 4-byte Decimal32 to a java.math.BigDecimal:

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);

The method toBigDecimal throws DecimalInconvertibleException if the decimal value is an infinity or NaN value. The actual type and sign can be obtained from the exception.

Encoding a java.math.BigDecimal to Decimal32 byte array:

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);

This will apply rounding if bigDecimal value doesn't fit a Decimal32, and overflow will 'round' to infinity.

If overflow to infinity is unwanted, then use:

BigDecimal bigDecimal = new BigDecimal("-7.50E-7");
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 the same for Decimal64 and Decimal128.

The valueOf methods exists for:

  • BigDecimal
  • BigInteger
    • In addition, there is valueOfExact(BigInteger) which throws DecimalOverflowException if the BigInteger needs to be rounded to fit the target decimal type.
  • String
  • double
  • Decimal (parent class of Decimal32, Decimal64 and Decimal128) to allow conversion between decimal types

The valueOf methods will round values to fit the target decimal type, and - depending on the specified overflow handling - will either return +/- infinity or throw an exception on overflow.

Conversion to a type is provided by:

  • toBytes()
  • toBigDecimal() - will throw DecimalInconvertibleException if the value is an infinity or NaN value
  • toString()
  • doubleValue()
  • toDecimal(Class) and toDecimal(Class, OverflowHandling)

To obtain a BigInteger, use toBigDecimal().toBigInteger() but be aware that large values (especially of Decimal128) can result in significant memory use.

The reason this library exists is that Firebird version 4.0 added support for the SQL DECFLOAT type (with a precision of 16 and 34 digits) using decimal64 and decimal128 in the protocol, and this support needed to be added to Jaybird, the Firebird JDBC driver.

As I was unable to find an existing library for this (maybe my Google-fu is lacking though), I created one. As I believe others may have similar needs, I decided to release it as a separate library.

I have tried to keep this library generically usable, but I'm sure this raison d'être has informed a number of design and implementation decisions. Pull requests and suggestions for improvements are welcome.

Jaybird does not directly depend on this library, but instead contains a copy to reduce the number of dependencies. External dependencies for JDBC drivers are an annoyance in non-Maven/Gradle environments.

SPDX-License-Identifier: MIT

联系我们 contact @ memedata.com