把一个IEEE754浮点数转换为IBM370浮点数的C#代码。
在这个上有古老的IBM370浮点格式的说明。
// 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 }
在这段C代码的基础上修改的
/* Assumes sizeof(int) == 4 */static void float_to_ibm(int from[], int to[], int n, int endian)/********************************************************************** float_to_ibm - convert between 32 bit IBM and IEEE floating numbers*********************************************************************** Input:from input vectorn number of floats in vectorsendian =0 for little endian machine, =1 for big endian machinesOutput:to output vector, can be same as input vector*********************************************************************** Notes:Up to 3 bits lost on IEEE -> IBMIBM -> IEEE may overflow or underflow, taken care of by substituting large number or zeroOnly integer shifting and masking are used.*********************************************************************** Credits: CWP: Brian Sumner***********************************************************************/{ register int fconv, fmant, i, t; for (i=0;i> 23) - 126; while (t & 0x3) { ++t; fmant >>= 1; } fconv = (0x80000000 & fconv) | (((t>>2) + 64) << 24) | fmant; } if(endian==0) fconv = (fconv<<24) | ((fconv>>24)&0xff) | ((fconv&0xff00)<<8) | ((fconv&0xff0000)>>8); to[i] = fconv; } return; }
另外找到的一些C代码放在这里以后备用
#include "ibmieee.h" /*--------------------------------------------------------------------- * * FILE: ./ibmieee.c * *----------------------------------------------------------------------** DESCRIPTION:* Conversion from IBM to IEEE format* Byte order is detected and accounted for using* define constant 'L_ENDIAN'**----------------------------------------------------------------------* ROUTINES DEFINED IN THIS MODULE: *----------------------------------------------------------------------** * Convert IBM to IEEE integer:** ibm_ieee_i( n, ibm, ieee)* int n;* int *ibm;* int *ieee;* * Convert IEEE to IBM integer:** ieee_ibm_i( n, ieee, ibm)* int n;* int *ieee;* int *ibm;* * Convert IBM to IEEE short floating point:** ibm_ieee_f( n, ibm, ieee)* int n;* char *ibm;* float *ieee;* * Convert IEEE to IBM floating point:** ieee_ibm_f( n, ieee, ibm)* int n;* float *ieee;* char *ibm;**---------------------------------------------------------------------*/ void ibm_ieee_i( int n, char *ibm, char *ieee ) /* Convert from IBM to IEEE integer, possibly in-place*/ #ifdef L_ENDIAN { int j; char temp; /* Reverse byte order on little endian machines */ for (j=0; j<4*n; j+=4) { temp=ibm[j]; ieee[j]=ibm[j+3]; ieee[j+3]=temp; temp=ibm[j+1]; ieee[j+1]=ibm[j+2]; ieee[j+2]=temp; } #else { int j; /* Move words if not same location */ if (ibm != ieee) for (j=0; j<< 1; }; /* Discard MSB and decrement exponent 1 more */ tmp1.u = tmp1.u & 0x007FFFFF; exp--; /* Check for exponent overflow or underflow */ if (exp & 0xFF00) { if (exp < 0) /* Underflow */ ieee[i].c[0] = ieee[i].c[1] = ieee[i].c[2] = ieee[i].c[3] = '\0'; else { /* Overflow */ #ifdef L_ENDIAN ieee[i].c[3] = 0x7F; ieee[i].c[2] = 0x80; ieee[i].c[1] = 0x00; ieee[i].c[0] = 0x00; #else ieee[i].c[0] = 0x7F; ieee[i].c[1] = 0x80; ieee[i].c[2] = 0x00; ieee[i].c[3] = 0x00; #endif } iret = 1; continue; } /* Move exponent into proper field and set sign bit */ tmp2.u = 0; #ifdef L_ENDIAN tmp2.c[3] = (char)exp; tmp2.u = tmp2.u >> 1; if (temp.u & 0x00000080) tmp2.u = tmp2.u | 0x80000000; else tmp2.u = tmp2.u & 0x7fffffff; #else tmp2.c[0] = (char)exp; tmp2.u = tmp2.u >> 1; tmp2.u = tmp2.u | (temp.u & 0x80000000); #endif /* Set output value */ temp.u = tmp1.u | tmp2.u; ieee[i].c[0] = temp.c[0]; ieee[i].c[1] = temp.c[1]; ieee[i].c[2] = temp.c[2]; ieee[i].c[3] = temp.c[3]; } return ; } /*********************************************************************/ void ieee_ibm_f( int n, VAL *ieee, VAL *ibm ) { int i; VAL temp,tmp1,tmp2; int exp,rem; for (i=0; i > 2) + 64; /* Normalize mantissa by shifting by (4-remainder) */ if (rem) { tmp1.u = tmp1.u >> (4-rem); exp = exp + 1; } /* Move exponent and mantissa bytes into IBM locations */ #ifdef L_ENDIAN tmp2.u = 0; tmp2.c[0] = (char)exp; tmp2.c[1] = tmp1.c[2]; tmp2.c[2] = tmp1.c[1]; tmp2.c[3] = tmp1.c[0]; /* Set sign bit */ if (temp.u & 0x80000000) tmp2.u = tmp2.u | 0x00000080; #else tmp2.u = tmp1.u; tmp2.c[0] = (char)exp; /* Set sign bit */ if (temp.u & 0x80000000) tmp2.u = tmp2.u | 0x80000000; #endif /* Set output value */ ibm[i].c[0] = tmp2.c[0]; ibm[i].c[1] = tmp2.c[1]; ibm[i].c[2] = tmp2.c[2]; ibm[i].c[3] = tmp2.c[3]; } return ; }