# IEEE754、VAX、IBM浮点型介绍和.NET中互相转换

【题外话】

【文章索引】

【一、IEEE754标准浮点数字的存储详解】

SEF      S        EEEEEEEE        FFFFFFF        FFFFFFFF        FFFFFFFF
bits     1        2      9        10                                    32
bytes    byte1           byte2                   byte3           byte4

Double S = (byte1 & 0x80) >> 7;
Double E = ((byte1 & 0x7F) << 1) + ((byte2 & 0x80) >> 7);
Double F = ((byte2 & 0x7F) << 16) + (byte3 << 8) + byte4;

V = (-1)^S * (F + C) * A^(E - B)

 二进制表示 十六进制表示 含义 十进制表示 0 11111111 00000000000000000000000 7F 80 00 00 正无穷 +∞ 1 11111111 00000000000000000000000 FF 80 00 00 负无穷 -∞ 0 00000000 00000000000000000000000 00 00 00 00 +0 0 1 00000000 00000000000000000000000 80 00 00 00 -0 0 0 00000000 00000000000000000000001 00 00 00 01 最小正数 1.401298E-45 0 11111110 11111111111111111111111 7F 7F FF FF 最大值 3.402823E+38 1 11111110 11111111111111111111111 FF 7F FF FF 最小值 -3.402823E+38 0 01111111 00000000000000000000000 3F 80 00 00 +1 1

 1 Single ToSingle(Byte[] data)
2 {
3     Double a = 2.0;
4     Double b = 127.0;
5     Double c = 1.0;
6     Double d = -126.0;
7
8     Byte byte1 = data[3];
9     Byte byte2 = data[2];
10     Byte byte3 = data[1];
11     Byte byte4 = data[0];
12
13     Double s = (byte1 & 0x80) >> 7;
14     Double e = ((byte1 & 0x7F) << 1) + ((byte2 & 0x80) >> 7);
15     Double f = ((byte2 & 0x7F) << 16) + (byte3 << 8) + byte4;
16     Double m = f / Math.Pow(2, 23);
17
18     if (e == 0xFF && f == 0) return (s == 0 ? Single.PositiveInfinity : Single.NegativeInfinity);
19     if (e == 0xFF && f != 0) return Single.NaN;
20     if (e == 0x00 && f == 0) return 0;
21     if (e == 0x00 && f != 0) return (Single)((s == 0 ? 1.0 : -1.0) * m * Math.Pow(a, d));
22
23     return (Single)((s == 0 ? 1.0 : -1.0) * (c + m) * Math.Pow(a, e - b));
24 }
25
26 Byte[] GetBytes(Single num)
27 {
28     Double a = 2.0;
29     Double b = 127.0;
30     Double c = 1.0;
31     Double d = Math.Log(2);
32
33     Int32 s = (num >= 0 ? 0 : 1);
34
35     Double v = Math.Abs(num);
36     Int32 e = (Int32)(Math.Log(v) / d + b);
37
38     Double m = (v / Math.Pow(a, e - b)) - c;
39     Int32 f = (Int32)(m * Math.Pow(2, 23));
40
41     Byte[] data = new Byte[4];
42     data[3] = (Byte)((s << 7) + ((e & 0xFE) >> 1));
43     data[2] = (Byte)(((e & 0x01) << 7) + ((f & 0x007F0000) >> 16));
44     data[1] = (Byte)((f & 0x0000FF00) >> 8);
45     data[0] = (Byte)(f & 0x000000FF);
46
47     return data;
48 }

【二、VAX及IBM浮点数字的存储和转换】

VAX单精度浮点：

SEF         S        EEEEEEEE        FFFFFFF        FFFFFFFF        FFFFFFFF
bits        1        2      9        10                                    32
bytes       byte2           byte3                   byte0           byte1

IBM单精度浮点：

SEF         S        EEEEEEE        FFFFFFFF        FFFFFFFF        FFFFFFFF
bits        1        2     8        9                                      32
bytes       byte1                   byte2           byte3           byte4

 1 using System;
2
3 namespace DotMaysWind.Numerics
4 {
5     /// <summary>
6     /// VAX单精度浮点数字
7     /// </summary>
8     /// <remarks>
9     /// SEF         S        EEEEEEEE        FFFFFFF        FFFFFFFF        FFFFFFFF
10     /// bits        1        2      9        10                                    32
11     /// bytes       byte2           byte1                   byte4           byte3
12     /// </remarks>
13     public struct VAXSingle
14     {
15         #region 常量
16         private const Int32 LENGTH = 4;
17         private const Double BASE = 2.0;
18         private const Double EXPONENT_BIAS = 128.0;
19         private const Double MANTISSA_CONSTANT = 0.5;
20         private const Double E24 = 16777216.0;
21         #endregion
22
23         #region 字段
24         private Byte[] _data;
25         #endregion
26
27         #region 构造方法
28         /// <summary>
29         /// 初始化新的VAX单精度浮点数字
30         /// </summary>
31         /// <param name="data">VAX单精度浮点数字字节数组</param>
32         /// <param name="startIndex">数据起始位置</param>
33         public VAXSingle(Byte[] data, Int32 startIndex)
34         {
35             this._data = new Byte[VAXSingle.LENGTH];
36             Array.Copy(data, startIndex, this._data, 0, VAXSingle.LENGTH);
37         }
38
39         /// <summary>
40         /// 初始化新的VAX单精度浮点数字
41         /// </summary>
42         /// <param name="num">系统标准的单精度浮点数字</param>
43         public VAXSingle(Single num)
44         {
45             Int32 s = (num >= 0 ? 0 : 1);
46
47             Double v = Math.Abs(num);
48             Int32 e = (Int32)(Math.Log(v) / Math.Log(2.0) + 1.0 + VAXSingle.EXPONENT_BIAS);
49
50             Double m = (v / Math.Pow(VAXSingle.BASE, e - VAXSingle.EXPONENT_BIAS)) - VAXSingle.MANTISSA_CONSTANT;
51             Int32 f = (Int32)(m * VAXSingle.E24);
52
53             this._data = new Byte[VAXSingle.LENGTH];
54             this._data[1] = (Byte)((s << 7) + ((e & 0xFE) >> 1));
55             this._data[0] = (Byte)(((e & 0x01) << 7) + ((f & 0x007F0000) >> 16));
56             this._data[3] = (Byte)((f & 0x0000FF00) >> 8);
57             this._data[2] = (Byte)(f & 0x000000FF);
58         }
59         #endregion
60
61         #region 方法
62         /// <summary>
63         /// 获取系统标准的单精度浮点数字
64         /// </summary>
65         /// <returns>系统标准的单精度浮点数字</returns>
66         public Single ToSingle()
67         {
68             Byte b1 = this._data[1];
69             Byte b2 = this._data[0];
70             Byte b3 = this._data[3];
71             Byte b4 = this._data[2];
72
73             Double s = (b1 & 0x80) >> 7;
74             Double e = ((b1 & 0x7F) << 1) + ((b2 & 0x80) >> 7);
75             Double f = ((b2 & 0x7F) << 16) + (b3 << 8) + b4;
76             Double m = f / VAXSingle.E24;
77
78             if (e == 0 && s == 0) return 0;
79             if (e == 0 && s == 1) return Single.NaN;
80
81             return (Single)((s == 0 ? 1.0 : -1.0) * (VAXSingle.MANTISSA_CONSTANT + m) * Math.Pow(VAXSingle.BASE, e - VAXSingle.EXPONENT_BIAS));
82         }
83
84         /// <summary>
85         /// 获取VAX单精度浮点数据字节数组
86         /// </summary>
87         /// <returns>字节数组</returns>
88         public Byte[] ToArray()
89         {
90             Byte[] data = new Byte[VAXSingle.LENGTH];
91
92             Array.Copy(this._data, data, VAXSingle.LENGTH);
93
94             return data;
95         }
96         #endregion
97     }
98 }
View Code

 1 using System;
2
3 namespace DotMaysWind.Numerics
4 {
5     /// <summary>
6     /// IBM单精度浮点数字
7     /// </summary>
8     /// <remarks>
9     /// SEF         S        EEEEEEE        FFFFFFFF        FFFFFFFF        FFFFFFFF
10     /// bits        1        2     8        9                                      32
11     /// bytes       byte1                   byte2           byte3           byte4
12     /// </remarks>
13     public struct IBMSingle
14     {
15         #region 常量
16         private const Int32 LENGTH = 4;
17         private const Double BASE = 16.0;
18         private const Double EXPONENT_BIAS = 64.0;
19         private const Double E24 = 16777216.0;
20         #endregion
21
22         #region 字段
23         private Byte[] _data;
24         #endregion
25
26         #region 构造方法
27         /// <summary>
28         /// 初始化新的IBM单精度浮点数字
29         /// </summary>
30         /// <param name="data">IBM单精度浮点数字字节数组</param>
31         /// <param name="startIndex">数据起始位置</param>
32         public IBMSingle(Byte[] data, Int32 startIndex)
33         {
34             this._data = new Byte[IBMSingle.LENGTH];
35             Array.Copy(data, startIndex, this._data, 0, IBMSingle.LENGTH);
36         }
37
38         /// <summary>
39         /// 初始化新的IBM单精度浮点数字
40         /// </summary>
41         /// <param name="num">系统标准的单精度浮点数字</param>
42         public IBMSingle(Single num)
43         {
44             Int32 s = (num >= 0 ? 0 : 1);
45
46             Double v = Math.Abs(num);
47             Int32 e = (Int32)(Math.Log(v) / Math.Log(2.0) / 4.0 + 1.0 + IBMSingle.EXPONENT_BIAS);
48
49             Double m = (v / Math.Pow(IBMSingle.BASE, e - IBMSingle.EXPONENT_BIAS));
50             Int32 f = (Int32)(m * IBMSingle.E24);
51
52             this._data = new Byte[IBMSingle.LENGTH];
53             this._data[3] = (Byte)(s + e);
54             this._data[2] = (Byte)((f & 0x00FF0000) >> 16);
55             this._data[1] = (Byte)((f & 0x0000FF00) >> 8);
56             this._data[0] = (Byte)(f & 0x000000FF);
57         }
58         #endregion
59
60         #region 方法
61         /// <summary>
62         /// 获取系统标准的单精度浮点数字
63         /// </summary>
64         /// <returns>系统标准的单精度浮点数字</returns>
65         public Single ToSingle()
66         {
67             Byte b1 = this._data[3];
68             Byte b2 = this._data[2];
69             Byte b3 = this._data[1];
70             Byte b4 = this._data[0];
71
72             Double s = (b1 & 0x80) >> 7;
73             Double e = (b1 & 0x7F);
74             Double f = (b2 << 16) + (b3 << 8) + b4;
75             Double m = f / IBMSingle.E24;
76
77             if (e == 0 && f == 0 && s == 0) return 0;
78
79             return (Single)((s == 0 ? 1.0 : -1.0) * m * Math.Pow(IBMSingle.BASE, e - IBMSingle.EXPONENT_BIAS));
80         }
81
82         /// <summary>
83         /// 获取IBM单精度浮点数据字节数组
84         /// </summary>
85         /// <returns>字节数组</returns>
86         public Byte[] ToArray()
87         {
88             Byte[] data = new Byte[IBMSingle.LENGTH];
89
90             Array.Copy(this._data, data, IBMSingle.LENGTH);
91
92             return data;
93         }
94         #endregion
95     }
96 }
View Code

【三、双精度浮点数的处理】

SEF    S     EEEEEEE EEEE  FFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF
bits   1     2          12 13                                                       64
bytes  byte1         byte2      byte3    byte4    byte5    byte6    byte7    byte8

VAX双精度浮点：

SEF    S     EEEEEEEE     FFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF
bits   1     2      9     10                                                          64
bytes  byte2        byte3         byte0    byte1    byte6    byte7    byte4    byte5

IBM双精度浮点：

SEF    S     EEEEEEE  FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF
bits   1     2     8  9                                                            64
bytes  byte1          byte2    byte3    byte4    byte5    byte6    byte7    byte8

【相关链接】

1. Transform between IEEE, IBM or VAX floating point number formats and bytes expressions：http://www.codeproject.com/Articles/12363/Transform-between-IEEE-IBM-or-VAX-floating-point-n
2. VAX F_FLOAT and D_FLOAT to IEEE T_FLOAT and S_FLOAT (double)：http://yaadc.blogspot.com/2013/01/vax-ffloat-and-dfloat-to-ieee-tfloat.html
3. IEEE Arithmetic：http://docs.oracle.com/cd/E19957-01/806-3568/ncg_math.html
4. Floating-Point：http://andromeda.rutgers.edu/~dupre/231/lecture13.doc
5. IBM Floating Point Architecture：http://en.wikipedia.org/wiki/IBM_Floating_Point_Architecture
6. VAX floating point to Decimal：http://arstechnica.com/civis/viewtopic.php?f=20&t=171682
posted @ 2013-10-14 00:27  大魔王mAysWINd  阅读(3289)  评论(2编辑  收藏  举报