Java 中的 x86 80 位浮点类型

x86 80-bit floating point type in Java

我想模拟 x86 扩展精度类型并执行算术运算并转换为 Java 中的其他类型。

我可以尝试使用 BigDecimal 来实现它,但是涵盖所有围绕 NaN、无穷大和强制转换的特殊情况可能是一项乏味的任务。我知道一些库提供比 double 精度更高的其他浮点类型,但我希望具有与 x86 80 位浮点相同的精度。

有Java库提供这样的浮点类型吗?如果没有,您能否提供其他提示,以比提出自定义 BigDecimal 解决方案更轻松地实现此类数据类型?

如果您知道您的 Java 代码实际上会 运行 在 x86 处理器上,请在汇编(或 C,如果 C 编译器支持的话)中实现 80 位算法并调用JNI.

如果您的目标是特定的非 x86 平台,请查看 qemu 代码。应该有一些方法可以只删除执行 80 位浮点运算的部分。 (编辑:qemu 的实现是 SoftFloat。)。用 JNI 调用它。

如果你真的想要跨平台的纯Java 80 位算法,你可能仍然可以将它与开源 CPU 模拟器中的 C 实现进行比较,以确保你解决正确的极端情况。

这与 java strictfp 选项有点相反,即 将计算限制 为 8 字节,而它执行 80 位。

所以我的答案是 运行 64 位机器上的 JVM,也许在某些 hypervisor/OS VM 中,所以你有一个开发平台。

80 位值最好由 long(尾数)和 int(指数和符号)组合而成。对于许多操作,将 long 的上半部分和下半部分放入单独的 "long" 值中可能是最实用的,因此将两个具有匹配符号和指数的数字相加的代码可能类似于:

long resultLo = (num1.mant & 0xFFFFFFFFL)+(num2.mant & 0xFFFFFFFFL);
long resultHi = (num1.mant >>> 32)+(num2.mant >>> 32)+(resultLo >>> 32);
result.exp = num1.exp; // Should match num2.exp
if (resultHi > 0xFFFFFFFFL) {
  exponent++;
  resultHi = (resultHi + ((resultHi & 2)>>>1)) >>> 1; // Round the result
}
rest.mant = (resultHi << 32) + resultLo;

周围有点麻烦,但并非完全不可行。关键是 将数字分解成足够小的部分,以便您可以像这样进行所有数学运算 输入 "long".

顺便说一句,请注意,如果其中一个数字最初没有相同的指数, 有必要跟踪是否有任何位 "fell off the end" 将它向左或向右移动以匹配第一个数字的指数,以便 之后能够正确地舍入结果。