把一个IEEE754浮点数转换为IBM370浮点数的C#代码
把一个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#代码的更多相关文章
- [SQL]当输入表达式得数为一个有效的整数、浮点数、money 或 decimal 类型,那么 ISNUMERIC 返回 1;否则返回 0
ISNUMERIC ( expression ) 当输入表达式得数为一个有效的整数.浮点数.money 或 :否则返回 .返回值为 确保可以将 expression 转换为上述数字类型中的一种. 注意 ...
- 浮点数转换为人名币读法字符串(JAVA)
/*<java疯狂讲义>浮点数转换为人名币读法字符串这个用例,感觉没有考虑零的情况*/ import java.util.Arrays; public class Num2Rmb { pr ...
- float:浮点型double:双精度实型decimal:数字型单精度浮点数(Single)双精度浮点数(double)
单精度浮点数(Single) 双精度浮点数(double) Decimal为SQL Server.MySql等数据库的一种数据类型,不属于浮点数类型,可以在定义时划定整数部分以及小 ...
- 把一个一维数组转换为in ()
把一个一维数组转换为in()形式. function dbCreateIn($itemList) { if(empty($itemList )){ return " IN ('') &quo ...
- Bean-Query 一个把对象转换为Map的Java工具库
刚开源了一个经过完整測试的Java工具类. 地址例如以下: https://github.com/Jimmy-Shi/bean-query 使用说明例如以下: Bean-query Click Her ...
- 小朋友学C语言(4):单精度浮点数与双精度浮点数
上节课简单介绍了浮点数.计算机程序中的浮点数分为单精度浮点数和双精度浮点数. 单精度和双精度精确的范围不一样. 计算机里的最基本的存储单位用位(bit)来表示.bit只能用来存储0或1. 稍大一点的单 ...
- 如何在一个网站或者一个页面,去书写你的JS代码
// JavaScript Document //如何在一个网站或者一个页面,去书写你的JS代码: //1.js的分层(功能) : jquery(tools) 组件(ui) 应用(app), mvc( ...
- 通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的
秦鼎涛 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验一 通过汇编一个简单的C程序,分析汇编代码 ...
- 通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的
实验一:通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的 学号:20135114 姓名:王朝宪 注: 原创作品转载请注明出处 <Linux内核分析>MOOC课程http: ...
随机推荐
- n位格雷曼实现
参考: 格雷码的实现 问题:产生n位元的所有格雷码. 格雷码(Gray Code)是一个数列集合,每个数使用二进位来表示,假设使用n位元来表示每个数字,任两个数之间只有一个位元值不同. 例如以下为 ...
- 详解Android微信登录与分享
Android 使用微信登录.分享功能 具体的文档详情微信官网上介绍(微信官网文档),本人直接按照项目部署步骤进行讲解: 第一步:申请你的AppID: 第二步:依赖 dependencies { co ...
- js对数组进行浅复制,深复制的方法
js 数组常用方法,数组的拷贝(不影响原数组),数组相等 置顶2017年07月17日 17:39:26 阅读数:4640 改变原数组的方法: pop();删除尾部的第一个元素并且返回这个元素: var ...
- webservice(一) 概念
Web service:是一个平台独立的,低耦合的,自包含的.基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述.发布.发现.协调和配置这些应用程序,用于开发分 ...
- 使用docker-compose编排django、mysql实战
背景: 本萌最近在部署自己开发的项目的时候发现同一套代码上传到服务器上后,部分功能莫名其妙的有点问题,服务器的各项配置都没有做过变动,所以想把项目转战到docker. 奈何刚接触docker,很多地方 ...
- [Linux] 关于 history 命令的简单使用
1. 如果不想记录当前 会话操作的命令的话 可以使用命令 set +o history 但是这个命令有一个坏处, 他自己被记住了... 2. 还有一个办法 就是 在退出登录之前执行命令 history ...
- [转帖]sqlnet.ora常用参数
sqlnet.ora常用参数 注﹕在修改sqlnet.ora文件之后重新启动监听﹐修改才能生效﹗﹗﹗ oracle网络设置主要包括三个文件,sqlnet.ora\ lisnter.ora\ tnsna ...
- poj 1144(割点)
题目链接:http://poj.org/problem?id=1144 题意:给出一个无向图,求关键节点的个数. 分析:双连通分量Tarjan算法直接求割点就行了,裸的模板题. AC代码: #incl ...
- 初入码田--ASP.NET MVC4 Web应用开发之二 实现简单的增删改查
初入码田--ASP.NET MVC4 Web应用之创建一个空白的MVC应用程序 初入码田--ASP.NET MVC4 Web应用开发之一 实现简单的登录 2016-07-29 一.创建M002Adm ...
- 【.Net】c# 让double保留两位小数
1.Math.Round(0.333333,2);//按照四舍五入的国际标准2. double dbdata=0.335333; string str1=String.Format(&qu ...