提问人:box 提问时间:10/29/2015 最后编辑:Peter Cordesbox 更新时间:11/13/2023 访问量:1675
Java 中的 x86 80 位浮点类型
x86 80-bit floating point type in Java
问:
我想模拟 x86 扩展精度类型,并在 Java 中对其他类型执行算术运算和强制转换。
我可以尝试使用 BigDecimal 实现它,但涵盖围绕 NaN、无穷大和强制转换的所有特殊情况可能是一项繁琐的任务。我知道有些库为其他浮点类型提供比 double 更高的精度,但我希望具有与 x86 80 位浮点数相同的精度。
有没有提供这种浮点类型的 Java 库?如果没有,您能否提供其他提示,以便以比提出自定义 BigDecimal 解决方案更少的努力来实现此类数据类型?
答:
如果您知道您的 Java 代码实际上将在 x86 处理器上运行,请在汇编中实现 80 位算术(如果 C 编译器支持 C),并使用 JNI 进行调用。
如果您面向特定的非 x86 平台,请查看 qemu 代码。应该有某种方法可以撕掉执行 80 位浮点运算的部分。(编辑:qemu 的实现是 SoftFloat。用 JNI 调用它。
如果你真的想要跨平台的纯 Java 80 位算术,你可能仍然可以将它与开源 CPU 模拟器中的 C 实现进行比较,以确保你正在解决正确的极端情况。
评论
这与 java strictfp 选项相反,后者将计算限制为 8 个字节,而它执行 80 位。
所以我的答案是在 64 位机器上运行 JVM,也许在某些虚拟机管理程序/操作系统 VM 中,这样你就有了一个开发平台。
评论
strictfp
80 位值最好是 a(尾数)和 an 的组合,表示指数和符号。对于许多操作,将 long 的上半部分和下半部分放入单独的“long”值可能是最实用的,因此将两个具有匹配符号和指数的数字相加的代码可能是这样的:long
int
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”。
顺便说一句,请注意,如果其中一个数字最初没有相同的指数, 有必要跟踪是否有任何位“从末端掉下来”,当 向左或向右移动以匹配第一个数字的指数,以便 之后能够正确地对结果进行四舍五入。
评论
BigDecimal
不适合这个问题; 表示 10 次幂的十进制数;你想要的类型表示幂为 2 的二进制数,将它们混合在一起并不是一个好的计划。BigDecimal