java-IBM-IEEE双精度浮点字节转换 [英] java - IBM-IEEE double-precision floating point byte conversion

查看:363
本文介绍了java-IBM-IEEE双精度浮点字节转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在Java中对字节数组进行IBM-IEEE浮点转换。我能够使用 http://www.thecodingforums.com/threads/c-code-for-converting-ibm-370-floating-point-to-ieee-754.438469

>

但是我还需要转换双精度双精度型的字节。在我看来,所有地方似乎都只显示单精度转换。我得到的最接近的是 http:中的r8ibmieee函数: //spdf.sci.gsfc.nasa.gov/pub/documents/old/miscellaeous_documents_from_nssdc/b46645.txt ,但它使用C并集/位字段,并且仅将IBM转换为IEEE(而不是相反)。我希望有一个类似于第一个链接的解决方案,该链接采用字节数组或十六进制字符串并输出字节数组或十六进制字符串。有没有人有一种算法可以将双精度字节从IBM转换为IEEE,反之亦然,也可以在Java中运行?

解决方案

I从未见过,但在查看格式后我会尝试。 ( https://en.wikipedia.org/wiki/IBM_Floating_Point_Architecture#Double-precision_64-位 https://en.wikipedia.org/wiki/Double-precision_floating -point_format



我建议您使用 long (64位整数)值;这样会容易得多。您将字节数组转换为 long ,使用该数组转换浮点格式,然后转换生成的 long 返回一个字节数组。我不会告诉您如何在 long 和字节数组值之间进行转换,因为我不知道您的字节数组是小端还是大端。



IBM 64位浮点数的格式为

  1个符号位
7个指数位(16的幂),偏差= 64
56个尾数位

如果指数为 X 并且尾数位为bbbbb ... bbbbb,则浮点值(如果符号位为0)为16 ^( X -64)* 0.bbbbb ... bbbbb。



IEEE 754 64位浮点数的格式为

  1个符号位
11个指数位(2的幂),bias = 1023
52个尾数位,其中含一位

如果指数为 X 并且尾数位为bbbbb ... bbbbb,则浮点值(如果符号位为0)为2 ^( X -1023)* 1.bbbbb ... bbbbb。



所以现在您需要弄清楚如何以IEEE格式表示相同的值(尽可能靠近;因为IBM尾数更长,所以您可能会失去一些精度。


  1. 符号位将是


  2. 要计算IEEE指数的初始值:如果IBM指数为 X 1 ,而IEEE指数是 X 2 ,我们需要找到 X 2 使得16 ^( X 1 -64)= 2 ^( X 2 -1023)。左边等于2 ^(4 * X 1 -256),所以由于2的幂必须相同,所以我们得到 X 2 = 4 * X 1 -256 + 1023 = 4 * X 1 +767。


  3. 此时,如果IBM float的尾数为bbbbb ... bbbbb,则浮点值为sign * 2 ^( X 2 -1023)* 0.bbbbb ... bbbbb。但是,对于IEEE浮点数,我们必须排列尾数位,以便乘以1.bbbbb ... bbbbb。这意味着我们需要移动IBM尾数的尾数位,直到将1移到二进制点左侧的位。每次移动尾数时,都会将尾数加倍,这意味着必须通过从 X 2 减去1来进行补偿。因此,假设在步骤2之后,我们有 X 2 = 1031和尾数= 0011 0111 1100 ...我们所代表的数字是2 8 * 0.001101111100 .....我们需要将尾数左移3位,以将1移至二进制点的左位;因此,该数字等于2 5 * 1.101111100...。因此,此步骤之后的 X 2 将为1031-3 = 1028;


二进制数左侧的1该点不会进入IEEE浮点数。这是一个隐含的1。 IEEE浮点数的尾数位将为101111100。您剩下的值(不计算隐含的1)将仍然有56位。



毕竟,您需要将低4位切掉以使其达到IEEE float的52位。



符号位,指数字段( X 2 )以及构造64位IEEE浮点数所需的尾数位。


I need to do IBM-IEEE floating point conversions of byte arrays in Java. I was able to successfully do conversions of single-precision float bytes using http://www.thecodingforums.com/threads/c-code-for-converting-ibm-370-floating-point-to-ieee-754.438469.

But I also need to convert bytes of double-precision doubles. Everywhere I look seems to only show the single-precision conversion. The closest I've gotten is the r8ibmieee function in http://spdf.sci.gsfc.nasa.gov/pub/documents/old/miscellaeous_documents_from_nssdc/b46645.txt, but it uses C unions/bitfields and only converts IBM to IEEE (and not the reverse). I was hoping for a solution similar to the first link that takes a byte array or hex string and outputs a byte array or hex string. Does anyone have an algorithm for converting double-precision bytes from IBM to IEEE and vice versa that will work in Java?

解决方案

I've never seen one, but I'll try, after looking at the formats. (https://en.wikipedia.org/wiki/IBM_Floating_Point_Architecture#Double-precision_64-bit; https://en.wikipedia.org/wiki/Double-precision_floating-point_format)

I recommend that you work with long (64-bit integer) values; it will be much easier. You'll convert a byte array to a long, work with that to convert the floating-point format, and then convert the resulting long back to a byte array. I won't tell you how to convert between long and byte array values, since I don't know whether your byte arrays are little-endian or big-endian.

An IBM 64-bit float has the format

1  sign bit
7  exponent bits (power of 16), bias = 64
56  mantissa bits

If the exponent is X and the mantissa bits are bbbbb...bbbbb, then the value of the float (if the sign bit is 0) is 16^(X-64) * 0.bbbbb...bbbbb.

An IEEE 754 64-bit float has the format

1   sign bit
11  exponent bits (power of 2), bias = 1023
52  mantissa bits, with an implied a bit

If the exponent is X and the mantissa bits are bbbbb...bbbbb, the value of the float (if the sign bit is 0) is 2^(X-1023) * 1.bbbbb...bbbbb.

So now you need to figure out how to express the same value in the IEEE format (as close as possible; it's possible you might lose a few bits of precision, since the IBM mantissa is longer).

  1. The sign bit will be the same in both formats.

  2. To compute an initial value for the IEEE exponent: If the IBM exponent is X1, and the IEEE exponent is X2, we need to find X2 such that 16^(X1-64) = 2^(X2-1023). The left side will be equal to 2^(4*X1-256), so since the powers of 2 must be the same, this gives us X2 = 4*X1-256+1023 = 4*X1+767.

  3. At this point, if the mantissa of the IBM float is bbbbb...bbbbb, the floating-point value is sign * 2^(X2-1023) * 0.bbbbb...bbbbb. However, for an IEEE float, we have to arrange the mantissa bits so that we're multiplying by 1.bbbbb...bbbbb. This means that we need to shift the mantissa bits of the IBM mantissa until we shift a 1 into the bit place to the left of the binary point. Every time we shift the mantissa, we double it, which means that we have to compensate by subtracting 1 from X2. Thus, suppose that after step 2, we have X2=1031 and mantissa = 0011 0111 1100 ... The number we're representing is 28 * 0.001101111100..... We will need to shift the mantissa left 3 places to get the 1 into the bit left of the binary point; the number is thus equal to 25 * 1.101111100.... Thus, X2 after this step will be 1031 - 3 = 1028; that's the value that will go into the exponent field of the IEEE float.

The 1 to the left of the binary point does not go into the IEEE float. It's an "implied 1". The mantissa bits of the IEEE float will be 101111100..... Note that the IBM mantissa has 56 bits; the value you're left with, not counting the implied 1, will still have 56 bits. You will need to chop off the lower 4 bits to get it down to 52 for the IEEE float, and you may want to round.

After all this, you now have the sign bit, the exponent field (X2), and the mantissa bits you need to construct the 64-bit IEEE float.

这篇关于java-IBM-IEEE双精度浮点字节转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆