Decimal-Java 是一个用于在 java.math.BigDecimal 与 IEEE-754r 之间相互转换的库
Source: Hacker News
decimal-java
Decimal-java 是一个库,用于在 java.math.BigDecimal 与 IEEE‑754r(IEEE‑754‑2008)十进制字节表示之间相互转换。
Maven
从 Maven 获取 decimal-java:
<dependency>
<groupId>org.firebirdsql</groupId>
<artifactId>decimal-java</artifactId>
<version>2.0.1</version>
</dependency>
或使用以下坐标:
org.firebirdsql
decimal-java
2.0.1
许可证
此库遵循 MIT 许可证;另请参阅 LICENSE.md。
状态
API 稳定,预计不会更改。
- 版本 2.0.0 及以上需要 Java 17 或更高,并使用模块名
org.firebirdsql.decimal进行模块化。 - 版本 1.0.2 需要 Java 7 或更高,并声明自动模块名
org.firebirdsql.decimal。
Goals
该库提供 java.math.BigDecimal 与 IEEE‑754r 十进制格式之间的转换。具体支持的字节表示为:
decimal32decimal64decimal128
其他格式(任意精度十进制)暂无计划。
非目标
该库 不 包含对十进制值的数学运算。进行算术运算时,请使用带有 MathContext.DECIMAL128、MathContext.DECIMAL64 或 MathContext.DECIMAL32 的 BigDecimal。
用法
完整的 Javadoc(最新标记发布):
解码 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() 在值为无穷大或 NaN 时抛出 DecimalInconvertibleException;异常中包含实际的类型和符号。
编码 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);
如果 BigDecimal 不适合 Decimal32,会进行四舍五入;溢出则四舍五入为无穷大。若要拒绝溢出:
Decimal32 decimal32 = Decimal32.valueOf(bigDecimal, OverflowHandling.THROW_EXCEPTION);
byte[] bytes = decimal32.toBytes();
assertArrayEquals(new byte[] {(byte) 0xa1, (byte) 0xc0, 0x03, (byte) 0xd0}, bytes);
对 Decimal64 和 Decimal128 的转换方式类似。
可用的 valueOf 重载
BigDecimalBigInteger(包括在四舍五入时抛出DecimalOverflowException的valueOfExact(BigInteger))Stringdouble
父类 Decimal(Decimal32、Decimal64、Decimal128 的超类)同样提供十进制类型之间的转换。
转换方法
toBytes()toBigDecimal()– 对于无穷大/NaN 抛出DecimalInconvertibleExceptiontoString()doubleValue()toDecimal(Class)和toDecimal(Class, OverflowHandling)
若要获取 BigInteger,请使用 toBigDecimal().toBigInteger(),并注意大数值(尤其是 Decimal128)可能会占用大量内存。
背景
Firebird 4.0 在协议中引入了 SQL DECFLOAT 类型(精度为 16 位和 34 位),使用 decimal64 和 decimal128。Jaybird,Firebird 的 JDBC 驱动,需要支持这些格式。由于没有找到合适的库,decimal-java 被创建并作为独立项目发布,以供更广泛的使用。Jaybird 包含该库的副本,以避免在非 Maven/Gradle 环境中产生额外的依赖。
参考文献
- General Decimal Arithmetic – 通用十进制算术
- Decimal Arithmetic Encodings – 十进制算术编码
- A Summary of Densely Packed Decimal encoding – 密集打包十进制编码概述
- The decNumber Library – decNumber 库
- Firebird 4.0 Release Notes – Firebird 4.0 发布说明
SPDX-License-Identifier: MIT