把一个IEEE754浮点数转换为IBM370浮点数的C#代码

简介:

把一个IEEE754浮点数转换为IBM370浮点数的C#代码。

 

在这个网页上有古老的IBM370浮点格式的说明。

 

image

 

        // 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 vector
n          number of floats in vectors
endian     =0 for little endian machine, =1 for big endian machines

Output:
to         output vector, can be same as input vector

*********************************************************************** 
Notes:
Up to 3 bits lost on IEEE -> IBM

IBM -> IEEE may overflow or underflow, taken care of by 
substituting large number or zero

Only integer shifting and masking are used.
*********************************************************************** 
Credits:     CWP: Brian Sumner
***********************************************************************/
{
    register int fconv, fmant, i, t;

    for (i=0;i<n;++i) {
        fconv = from[i];
        if (fconv) {
            fmant = (0x007fffff & fconv) | 0x00800000;
            t = (int) ((0x7f800000 & fconv) >> 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<n; j++) 
    ieee[j] = ibm[j]; 
 
#endif /* L_ENDIAN */ 
 
    return ; 
 
  } 
 
  /*********************************************************************/ 
 
 void ieee_ibm_i( int n, char *ibm, char *ieee ) 
 /*
        Convert from IEEE to IBM 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=ieee[j]; 
      ibm[j]=ieee[j+3]; 
      ibm[j+3]=temp; 
      temp=ieee[j+1]; 
      ibm[j+1]=ieee[j+2]; 
      ibm[j+2]=temp; 
    } 
 
#else 
    { 
      int j; 
 
      /* Move words if not same location */ 
 
      if (ibm != ieee) 
    for (j=0; j<n; j++) 
      ibm[j] = ieee[j]; 
 
#endif /* L_ENDIAN */ 
      return ; 
 
    } 
 
 
    /*---------------------------------------------------------------------
*
*  Convert from IBM short real to IEEE short real
*
*
*  Bit formats for Big Endian processors (i.e. 68020, SPARC, RS6000):
*
*              0         1        2        3         Byte Offset
*          --------------------------------------
*  IBM     !S! EXP   !   MH   !   MM   !   ML   !
*          --------------------------------------
*           0 1     7 8     15 16    23 24    31     bit number
*
*              0         1        2        3         Byte Offset
*          --------------------------------------
*  IEEE    !S! EXP    !  MH   !   MM   !   ML   !
*          --------------------------------------
*           0 1      8 9    15 16    23 24    31     bit number
*
*
*  Bit formats for Little Endian processors (i.e. Intel 80x86):
*
*              3         2        1        0         byte offset
*          --------------------------------------
*  IBM     !   ML   !   MH   !   MH   !S!  EXP  !
*          --------------------------------------
*           31    24 23    16 15     8 7 6     0     bit number
*
*              3         2        1        0         byte offset
*          --------------------------------------
*  IEEE    !S!  EXP  !!  MH   !   MM   !   ML   !
*          --------------------------------------
*          31 30    23 22   16 15     8 7      0     bit number
*
*
*  ML, MM, and MH refer to the low, middle, and high order mantissa
*  bytes.  S is the sign bit, EXP is the exponent.  Bits and bytes
*  are numbered in order of increasing address in memory.  The fields
*  are shown in the order that a Hex constant in C would be used as
*  a mask for accessing bits.
*
*
* A floating point number in the IBM format is defined to be:
*
*      (sign) 0.(significand) * 16**(exponent-64)
*
* In the IEEE format, a floating point number is:
*
*      (sign) 1.(significand) * 2**(exponent-127)
*
* The differences are:
*
*       1. IBM assumes a 0 to left of decimal point,
*          IEEE assumes a 1 to left of decimal point.
*          Since the IBM format has 1 more bit for the significand,
*          they both have the same precision: 24 binary digits.
*
*       2. The base for the exponent is 16 for IBM, 2 for IEEE
*
*       3. The bias for the exponent is 64 for IBM, 127 for IEEE
*
*       4. The exponent is 7 bits for IBM, 8 for IEEE. The exponent
*          range is then -64 to +63 for IBM, -127 to +128 for IEEE.
*
*       5. Since the IBM format has base 16, the decimal exponent
*          range for IBM is about twice that for IEEE:
*          IBM:  0.1H * 16**(-64)  to  0.FFFFFFH * 16**(+63)
*            =   5.4 * 10**(-79)   to   7.2 * 10**(+75)
*          IEEE: 1.0H * 2**(-127)  to  1.FFFFFFH * 2**(+128)
*            =   5.9 * 10**(-39)   to   6.8 * 10**(+38)
*
* To convert IBM to IEEE:
*
*       1. Multiply IBM exponent by 4 to convert base from 16 to 2,
*          subtract 129 to adjust for difference in bias (16*4-127).
*
*       2. Shift the IBM significand left 1 bit and subtract 1 from
*          the exponent. If the significand MSB is still 0, repeat.
*
*       3. If the exponent overflows, set result to +-infinity. If
*          it underflows, set to +-zero.
*
*       4. Move the converted sign, significand, and exponent into
*          the appropriate fields for the IEEE format.
*
*
* To convert IEEE to IBM:
*
*       1. Get IEEE mantissa (bits 0-22). OR in a 1 in bit 23 to
*          account for assumed leading '1'.
*
*       2. Get IEEE exponent.  Add 1 to exponent to place the decimal
*          point before the '1' in the mantissa.  Subtract IEEE bias
*          of 127 to yield true base 2 exponent.
*
*       3. Divide IEEE exponent by 4 to convert to base 16 exponent:
*            0.X * 2**Y = 0.X * 16**(Y/4)
*          Save remainder from division.  If remainder is not zero:
*            0.X * 16**(I+1/4) = 2*(0.X) * 16**I = (1/8)0.X * 16**(I+1)
*            0.X * 16**(I+2/4) = 4*(0.X) * 16**I = (1/4)0.X * 16**(I+1)
*            0.X * 16**(I+3/4) = 8*(0.X) * 16**I = (1/2)0.X * 16**(I+1)
*          I.E., add 1 to exponent, shift mantissa right by
*          (4 - remainder).  Add IBM bias of 64 to exponent.
*
*       4. Move the converted sign, significand, and exponent into
*          the appropriate fields for the IBM format.
*
*
*---------------------------------------------------------------------*/ 
  
  void  ibm_ieee_f( int n, VAL *ibm, VAL *ieee ) 
  
    { 
      int i,iret; 
      VAL tmp1,tmp2,temp; 
      int exp; 
 
      iret = 0; 
 
      for (i=0; i<n; i++) { 
  
    /* Move IBM word to properly aligned temp location */ 
    temp.c[0] = ibm[i].c[0]; 
    temp.c[1] = ibm[i].c[1]; 
    temp.c[2] = ibm[i].c[2]; 
    temp.c[3] = ibm[i].c[3]; 
 
    /* check for true zero */ 
    if (temp.u == 0) { 
      ieee[i].c[0] = ieee[i].c[1] = ieee[i].c[2] =  
        ieee[i].c[3] = '\0'; 
      continue; 
    } 
    /* extract mantissa */ 
#ifdef L_ENDIAN 
    tmp1.c[0] = temp.c[3]; 
    tmp1.c[1] = temp.c[2]; 
    tmp1.c[2] = temp.c[1]; 
    tmp1.c[3] = '\0'; 
#else 
    tmp1.u = temp.u; 
    tmp1.c[0] = '\0'; 
#endif 
 
    /* Extract exponent */ 
    /* remove sign bit, multiply by 4, subtract bias difference */ 
    exp = ((temp.c[0] & 0x7F) << 2 ) - 129; 
 
    /* Shift mantissa up 1 bit until there is a 1 in the MSB */ 
    while ( (tmp1.u & 0x800000) == 0 ) { 
      exp--; 
      tmp1.u = tmp1.u << 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<n; i++) { 
 
    /* Move to properly aligned location */ 
    temp.c[0] = ieee[i].c[0]; 
    temp.c[1] = ieee[i].c[1]; 
    temp.c[2] = ieee[i].c[2]; 
    temp.c[3] = ieee[i].c[3]; 
    /* check for true zero */ 
    if (temp.u == 0) { 
      ibm[i].c[0] = ibm[i].c[1] = ibm[i].c[2] =  
        ibm[i].c[3] = '\0'; 
      continue; 
    } 
    /* extract mantissa, OR in leading '1' */ 
    tmp1.u = (temp.u & 0x007FFFFF) | 0x00800000; 
 
    /* Extract exponent */ 
    /* remove sign bit, shift up one bit */ 
    tmp2.u = (temp.u & 0x7F800000) << 1;     
    /* Add 1 for mantissa shift, subtract 127 for IEEE bias */ 
#ifdef L_ENDIAN 
    exp = (unsigned)tmp2.c[3] - 126; 
#else 
    exp = (unsigned)tmp2.c[0] - 126; 
#endif 
 
    /* Divide exponent by 4, save remainder, add IBM bias of 64 */ 
    rem = exp & 0x03; 
    exp = (exp >> 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 ; 
    } 

本文转自申龙斌的程序人生博客园博文,原文链接:http://www.cnblogs.com/speeding/p/3362769.html,如需转载请自行联系原作者

http://www.cnblogs.com/speeding/ 

相关文章
|
1月前
|
C# Windows
C#通过代码实现快捷键编辑
C#通过代码实现快捷键编辑
|
3月前
|
开发框架 .NET 编译器
C# 10.0中Lambda表达式的改进:更简洁、更灵活的代码编写体验
【1月更文挑战第21天】随着C#语言的不断发展,Lambda表达式作为一种简洁、高效的函数式编程工具,在C# 10.0中迎来了重要的改进。本文将详细探讨C# 10.0中Lambda表达式的新特性,包括参数类型的推断增强、自然类型的Lambda参数以及Lambda表达式的属性改进等。这些改进不仅简化了Lambda表达式的编写过程,还提升了代码的可读性和灵活性,为开发者带来了更优质的编程体验。
|
3月前
|
C# 开发者
C# 10.0中的文件范围命名空间:简化代码组织的新方式
【1月更文挑战第18天】C# 10.0引入了文件范围的命名空间,这是一种新的语法糖,用于更简洁地组织和管理代码。文件范围命名空间允许开发者在每个文件的基础上定义命名空间,而无需显式使用花括号包裹整个文件内容。本文将深入探讨文件范围命名空间的工作原理、使用场景以及它们为C#开发者带来的便利。
|
4月前
|
存储 人工智能 C#
【Unity 3D】C#中数组、集合、栈、队列、哈希表、字典的讲解(附测试代码)
【Unity 3D】C#中数组、集合、栈、队列、哈希表、字典的讲解(附测试代码)
36 0
|
5月前
|
开发框架 .NET C#
如何调试 C# Emit 生成的动态代码?
如何调试 C# Emit 生成的动态代码?
|
4月前
|
IDE C# 开发工具
C# | 多线程批量下载文件(创建N个线程同时批量下载文件,只需要几行代码而已)
批量下载文件时使用多线程可以有效缩短完成时间,本文将讲解如何使用C#+CodePlus扩展库快速完成多线程的文件下载。 大部分代码由IDE自动生成,需要我们自己编写的代码正好**10行**。也就是说,只需要10分钟,就可以手撸一个多线程的批量下载器。
88 0
C# | 多线程批量下载文件(创建N个线程同时批量下载文件,只需要几行代码而已)
|
2月前
|
数据采集 JSON 前端开发
从代码到内容:使用C#和Fizzler探索Instagram的深处
Instagram是一个流行的社交媒体平台,拥有数亿的用户和海量的图片和视频内容。如果您想要从Instagram上获取一些有用的信息或数据,您可能需要使用爬虫技术来自动化地抓取和分析网页内容。本文将介绍如何使用C#和Fizzler这两个强大的工具,来实现一个简单而高效的Instagram爬虫,从代码到内容,探索Instagram的深处。
|
3月前
|
存储 传感器 监控
工业相机如何实现实时和本地Raw格式图像和Bitmap格式图像的保存和相互转换(C#代码,UI界面版)
工业相机如何实现实时和本地Raw格式图像和Bitmap格式图像的保存和相互转换(C#代码,UI界面版)
31 0
|
3月前
|
存储 C# 容器
掌握 C# 变量:在代码中声明、初始化和使用不同类型的综合指南
变量是用于存储数据值的容器。 在 C# 中,有不同类型的变量(用不同的关键字定义),例如: int - 存储整数(没有小数点的整数),如 123 或 -123 double - 存储浮点数,有小数点,如 19.99 或 -19.99 char - 存储单个字符,如 'a' 或 'B'。Char 值用单引号括起来 string - 存储文本,如 "Hello World"。String 值用双引号括起来 bool - 存储具有两个状态的值:true 或 false
37 2
|
8月前
|
存储 C# 图形学
代码解析 C# 引用类型还是值类型
代码解析 C# 引用类型还是值类型