其实不论是float还是double在存储方式上都是遵从IEEE的规范 的,float遵从的是IEEE R32.24 ,而double 遵从的是R64.53。

     无论是单精度还是双精度在存储中都分为三个部分:

  1. 符号位(Sign) : 0代表正,1代表为负
  2. 指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储
  3. 尾数部分(Mantissa):尾数部分

      我们知道,浮点数在内存中是以科学记数法存储的,只不过我们用的是10进制,而计算机用的是2进制,例如 123456789.4321

  

关于指数,他们的表示方式是一个偏移量,float的为127,double的为1023,所以实际在指数位存储的值为 指数 + 1023

下面是我写的一个测试程序:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 
 6 namespace ConsoleViewer
 7 {
 8     class Program
 9     {
10         static void Main(string[] args)
11         {
12             double val = 123456789.4321;
13             int offset = 1023; 
14             long value = GetMemoryValue(val);
15             int sign = (int)(((ulong)value & 0x8000000000000000)>>63);
16             int e = (int)((value & 0x7FF0000000000000)>>52)-offset;
17             long d = (value & 0xFFFFFFFFFFFFF);
18             Console.WriteLine("123456789.4321 在内存内的布局方式:\r\n\r\n{0}\r\n", GetBinary(val));
19             double b = GetBaseNumber(d);
20             Console.WriteLine("符号位:{0}",sign);
21             Console.WriteLine("指数:{0}",e);
22             Console.WriteLine("底数小数部分(十进制):{0}",d);
23             Console.WriteLine("底数小数部分(二进制):\r\n{0}", GetBinary(d));
24             Console.WriteLine("十进制底数:{0}",b);
25             Console.WriteLine("验算:{0} * 2^{1} = {2}",b,e,b*Math.Pow(2,e));
26             Console.ReadLine();
27         }
28 
29         static double GetBaseNumber(long value)
30         {
31             double result = 0.0, u = 0x10000000000000;
32             long d = 0x1;
33             for (int i = 0; i < 52; i++)
34             {
35                 result += ((value & d) >> i) / u;
36                 d <<= 1;
37                 u /= 2;
38             }
39             return 1 + result;
40         }
41 
42         static unsafe long GetMemoryValue(double value)
43         {
44             return (*((long*)(&value)));
45         }
46 
47         static unsafe string GetBinary(double val)
48         {
49             char[] chars = new char[64];
50             ulong d = 1;
51             ulong value = *(ulong*)(&val);
52             for (int i = 0; i < 64; i++)
53             {
54                 chars[63-i] = ((char)((char)((d & value)>>i) + '0'));
55                 d <<= 1;
56             }
57             return new string(chars,0,64);
58         }
59 
60         static unsafe string GetBinary(long val)
61         {
62             char[] chars = new char[64];
63             ulong d = 1;
64             ulong value = *(ulong*)(&val);
65             for (int i = 0; i < 64; i++)
66             {
67                 chars[63 - i] = ((char)((char)((d & value) >> i) + '0'));
68                 d <<= 1;
69             }
70             return new string(chars, 0, 64);
71         }
72     }
73 }

上面的代码的运行结果见上图!

posted on 2013-03-26 15:31  猴哥猴哥  阅读(883)  评论(0编辑  收藏  举报