把一个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 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 ;
}

把一个IEEE754浮点数转换为IBM370浮点数的C#代码的更多相关文章

  1. [SQL]当输入表达式得数为一个有效的整数、浮点数、money 或 decimal 类型,那么 ISNUMERIC 返回 1;否则返回 0

    ISNUMERIC ( expression ) 当输入表达式得数为一个有效的整数.浮点数.money 或 :否则返回 .返回值为 确保可以将 expression 转换为上述数字类型中的一种. 注意 ...

  2. 浮点数转换为人名币读法字符串(JAVA)

    /*<java疯狂讲义>浮点数转换为人名币读法字符串这个用例,感觉没有考虑零的情况*/ import java.util.Arrays; public class Num2Rmb { pr ...

  3. float:浮点型double:双精度实型decimal:数字型单精度浮点数(Single)双精度浮点数(double)

        单精度浮点数(Single) 双精度浮点数(double)       Decimal为SQL Server.MySql等数据库的一种数据类型,不属于浮点数类型,可以在定义时划定整数部分以及小 ...

  4. 把一个一维数组转换为in ()

    把一个一维数组转换为in()形式. function dbCreateIn($itemList) { if(empty($itemList )){ return " IN ('') &quo ...

  5. Bean-Query 一个把对象转换为Map的Java工具库

    刚开源了一个经过完整測试的Java工具类. 地址例如以下: https://github.com/Jimmy-Shi/bean-query 使用说明例如以下: Bean-query Click Her ...

  6. 小朋友学C语言(4):单精度浮点数与双精度浮点数

    上节课简单介绍了浮点数.计算机程序中的浮点数分为单精度浮点数和双精度浮点数. 单精度和双精度精确的范围不一样. 计算机里的最基本的存储单位用位(bit)来表示.bit只能用来存储0或1. 稍大一点的单 ...

  7. 如何在一个网站或者一个页面,去书写你的JS代码

    // JavaScript Document //如何在一个网站或者一个页面,去书写你的JS代码: //1.js的分层(功能) : jquery(tools) 组件(ui) 应用(app), mvc( ...

  8. 通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的

    秦鼎涛  <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验一 通过汇编一个简单的C程序,分析汇编代码 ...

  9. 通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的

    实验一:通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的 学号:20135114 姓名:王朝宪 注: 原创作品转载请注明出处   <Linux内核分析>MOOC课程http: ...

随机推荐

  1. Internet History, Technology and Security (Week3)

    Week3. Welcome to week 3! This is our fourth and final week of History where we make the connection ...

  2. Prim's Algorithm & Kruskal's algorithm

    1. Problem These two algorithm are all used to find a minimum spanning tree for a weighted undirecte ...

  3. angularJS1笔记-(7)-控制器的合理使用(显示和隐式的依赖注入)

    AngularJS依赖注入 1.隐式注入:不需要开发人员干预,angularJS自动根据参数的名称识别和注入数据 app.controller("myCtrl".function( ...

  4. 网页访问过程(基于CDN)

    1. 全局负载均衡(基于DNS) 如果有多台 WEB 服务器同时为一个域名提供服务时,即一条 URL 对应多个 IP 地址,那么该 URL 的权威域名服务器可能会根据该 URL 解析出多个 IP 地址 ...

  5. vm的三种网络模式

    Vm网卡的模式:网络地址转换模式(nat),仅主机(host-only),桥接模式(Brideged) VMware 的几个虚拟设备: ■ VMnet0:这是 VMware 用于虚拟桥接网络下的虚拟交 ...

  6. web安全测试系统

    最近写了个简单的web安全实践系统部署到了docker中 下载方式:docker pull ju5ton1y/websecurity github Dockerfile下载地址:https://git ...

  7. 使用 Idea 打 scala程序的 jar 包 - 02

    Artifact ——>+  ——>JAR ——>From modules with dependencies 选择 Module,选择主函数,OK——>OK 勾选Includ ...

  8. Qt4问题集锦

    一.Qt程序发布后加载的jpg.jpeg图片不可见 问题的提出: 最近在客户机器上部署安装QT编写的软件,发现只要是jpg.jpeg格式的图片都无法显示出来.最后发现必须按如下述步骤才能显示jpg.j ...

  9. oracle +plsql装完省略号不能点

    1.如图 2.复制 TNS 服务名 3.复制到 登录框的 Database ,输入用户名密码,点OK..可以进去了,省略号变成可点击状态

  10. 【转】arm-none-linux-gnueabi-gcc下载

    arm-none-linux-gnueabi-gcc是 Codesourcery 公司(目前已经被Mentor收购)基于GCC推出的的ARM交叉编译工具.可用于交叉编译ARM系统中所有环节的代码,包括 ...