daT*_*ake 5 java type-conversion extended-precision
我正在开发一个程序,它将真正旧的 Open Access 4 .df 文件转换为其他格式,并创建数据库脚本 - 我已经能够转换除十进制类型之外的所有可能的类型。我发现字节顺序必须是 80 位扩展精度。我已经尝试自己进行转换,但无法将 80 位扩展精度(https://en.wikipedia.org/wiki/Extended_ precision#x86_Extended_Precision_Format )转换为字符串以及将字符串转换为 80 位扩展精度Java 中的精度。
价值:1,235
来自 df 文件的十六进制:40 00 9e 06 52 14 1e f0 db f6
价值:0,750
来自 df 文件的十六进制:3f ff c0 00 00 00 00 00 00 00
也许有人可以帮助转换?
此致
@EJP评论:好吧,我扔掉了最后16位,所以我得到了 3f ff c0 00 00 00 00 00 关于(Java - Convert hex to IEEE-754 64-bit float - double precision)我尝试将其转换为
String hex = "3fffc00000000000";
long longBits = Long.valueOf(hex ,16).longValue();
double doubleValue = Double.longBitsToDouble(longBits);
Run Code Online (Sandbox Code Playgroud)
但结果是 1,984375 而不是 0,750
我不确定它是否有资格作为答案,或者是否可以回答,因为......你确定它是标准的 80 位浮点格式吗?因为事实上,它看起来有点奇怪。举你的第一个例子:
\n\n40 00 9e...
\n\n这里,0x4000\xe2\x88\x9216383=1 是指数。尾数以 MSB 开头1,对应于整数部分,因此它的形式应该为 1,... x 2^1,大于 2。但你说它应该是 1,235。没有意义。
我用 Java 创建了这个丑陋的 hack 来组装双精度数:
\n\nlong high = 0x40_00L;\nlong low = 0x9e_06_52_14_1e_f0_db_f6L;\nlong e = (((high & 0x7FFFL) - 16383) + 1023) & 0x7FFL;\nlong ld = ((high & 0x8000L) << 48)\n | (e << 52)\n | ((low >>> 11) & 0xF_FFFF_FFFF_FFFFL);\nSystem.out.printf("%16X\\n", ld);\ndouble d = Double.longBitsToDouble(ld);\nSystem.out.println(d);\nRun Code Online (Sandbox Code Playgroud)\n\n假设输入是正确的 80 位值,该片段应该可以正常工作,除非它无法正确舍入、不检查溢出、不处理非标准化值并且可能无法处理 NaN 等特殊值。对于这个输入,它打印
\n\n4003C0CA4283DE1B\n2.46913578\nRun Code Online (Sandbox Code Playgroud)\n\n不是1,235!然后我使用了这个C++代码(用GCC编译,其中long double是80位格式):
#include <stdio.h>\n\nint main() {\n long long high = 0x4000;\n long long low = 0x9e0652141ef0dbf6;\n long double d;\n char *pd = (char*)&d, *ph = (char*)&high, *pl = (char*)&low;\n for (int i = 0; i < 8; ++i) {\n pd[i] = pl[i];\n }\n for (int i = 0; i < 2; ++i) {\n pd[8 + i] = ph[i];\n }\n printf("%lf\\n", (double) d);\n}\nRun Code Online (Sandbox Code Playgroud)\n\n它还打印 2.469136。
\n