从IBM浮点转换为IEEE浮点标准和反向Versa In C#?

时间:2010-12-28 23:28:22

标签: c# c floating-point ieee-754

正在为我们正在使用的旧系统寻找IEEE浮点数到IBM浮点格式的方法。

我们可以在C#中使用通用公式吗?

4 个答案:

答案 0 :(得分:6)

// http://en.wikipedia.org/wiki/IBM_Floating_Point_Architecture
// float2ibm(-118.625F) == 0xC276A000
// 1 100 0010    0111 0110 1010 0000 0000 0000
// IBM/370 single precision, 4 bytes
// xxxx.xxxx xxxx.xxxx xxxx.xxxx xxxx.xxxx
// s|-exp--| |--------fraction-----------|
//    (7)          (24)
// value = (-1)**s * 16**(e - 64) * .f   range = 5E-79 ... 7E+75
static int float2ibm(float from)
{
    byte[] bytes = BitConverter.GetBytes(from);
    int fconv = (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8)| bytes[0];

    if (fconv == 0) return 0;
    int fmant = (0x007fffff & fconv) | 0x00800000;
    int t = (int)((0x7f800000 & fconv) >> 23) - 126;
    while (0 != (t & 0x3)) { ++t; fmant >>= 1; }
    fconv = (int)(0x80000000 & fconv) | (((t >> 2) + 64) << 24) | fmant;
    return fconv; // big endian order
}

我更改了一段名为static void float_to_ibm的代码(int从[],int到[],int n,int endian) 上面的代码可以在PC上正确运行 from 是小端的浮点数。 返回值是大端ibm浮点数,但存储在int类型中。

答案 1 :(得分:2)

一种显而易见的方法是使用数字的文本表示作为交换格式。

答案 2 :(得分:0)

我最近不得不将一个浮点数转换为另一个浮点数。看起来XDR格式的浮点数使用奇数格式。因此,当从XDR转换为标准浮点数时,此代码就可以实现。

#include <rpc/rpc.h>

// Read in XDR float array, copy to standard float array
// out array needs to be allocated before the function call

bool convertFromXdrFloatArray(float *in, float *out, long size)
{
    XDR xdrs;
    xdrmem_create(&xdrs,(char *)in, size*sizeof(float), XDR_DECODE);

    for(int i = 0; i < size; i++)
    {
        if(!xdr_float(&xdrs, out++)) {
            fprintf(stderr,"%s:%d:ERROR:xdr_float\n",__FILE__,__LINE__);
            exit(1);
        }
    }
    xdr_destroy(&xdrs);

    return true;
}

答案 3 :(得分:0)

使用第一个答案我添加了以下可能在某些情况下有用的内容:

  

///

  /// Converts an IEEE floating number to its string representation (4 or 8 ascii codes).
    /// Useful for SAS XPORT files format.
    /// </summary>
    /// <param name="from_">IEEE number</param>
    /// <param name="padTo8_">When true, output is 8 chars rather than 4</param>
    /// <returns>Printable string according to hardware's endianness</returns>
    public static string Float2IbmAsAsciiCodes(float from_, bool padTo8_ = true)
    {
        StringBuilder sb = new StringBuilder();
        string s;
        byte[] bytes = BitConverter.GetBytes(Float2Ibm(from_)); // big endian order

        if (BitConverter.IsLittleEndian)
        {
            // Revert bytes order
            for (int i = 3; i > -1; i--)
                sb.Append(Convert.ToChar(bytes[i]));
            s = sb.ToString();
            if (padTo8_)
                s = s.PadRight(8, '\0');
            return s;
        }
        else
        {
            for (int i = 0; i < 8; i++)
                sb.Append(Convert.ToChar(bytes[i]));
            s = sb.ToString();
            if (padTo8_)
                s = s.PadRight(8, '\0');
            return s;
        }
    }