Reputation: 129
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
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
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
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
Reputation: 613232
An obvious approach would be to use textual representation of the number as the interchange format.
Upvotes: 2