aiw
aiw

Reputation: 129

Convert from the IBM floating point to the IEEE floating point standard and vice versa in C#

I was looking for a way to convert IEEE floating point numbers to IBM floating point format for a old system we are using.

Is there a general formula we can use in C# to this end?

Upvotes: 8

Views: 4943

Answers (4)

speeding
speeding

Reputation: 133

Use:

// https://en.wikipedia.org/wiki/IBM_hexadecimal_floating-point
//
// 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 fromFormat)
{
    byte[] bytes = BitConverter.GetBytes(fromFormat);
    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
}

I changed a piece of code called static void float_to_ibm(int from[], int to[], int n, int endian).

The code above can be run correctly on a PC.

from is a little-endian float number. return value is a big-endian IBM float number, but stored in type int.

Upvotes: 9

barbara.post
barbara.post

Reputation: 1661

Using speeding's answer, I added the following that may be useful in some cases:

/// <summary>

/// Converts an IEEE floating number to its string representation (4 or 8 ASCII codes).
/// It is useful for SAS XPORT files format.
/// </summary>
/// <param name="from_">IEEE number</param>
/// <param name="padTo8_">When true, the output is 8 characters rather than 4</param>
/// <returns>Printable string according to the 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;
    }
}

Upvotes: 0

phyatt
phyatt

Reputation: 19122

I recently had to convert one float to another. It looks like the XDR format uses an odd format for its floats. So when converting from XDR to standard floats, this code did it.

#include <rpc/rpc.h>

// Read in an XDR float array, copy to a standard float array.
// The '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;
}

Upvotes: 0

David Heffernan
David Heffernan

Reputation: 613232

An obvious approach would be to use textual representation of the number as the interchange format.

Upvotes: 2

Related Questions