浮点数的内存存储和运算

本文以单精度的内存存储来说明的

0X01 浮点数的内存存储

IEEE 754浮点数标准规定的浮点数结构:

S E M 公式{V=(-1)S*2E*M ;E=e-Bias} 偏移量
单精度 1 8 23 (-1)S*2(e-127)*M ;(Bias = 127) 127
双精度 1 11 52 (-1)S*2(e-1023)*M;(Bias = 1023) 1023

S是符号位,E是阶码,Bias = 2k-1 -1
M是尾数编码,尾数m为内存中小数字段,其值依赖于阶码e是否为0,当e!=0时M=1.m;当e=0时M=0.m;
其中S符号位,只有0和1,分别表示正负;E阶码,通常使用移码表示(原码、反码、补码和移码详解)。

二进制存储结构(单精度浮点数):

单精度 S(第31位) e((30位到23位)) m(22位到0位)
双精度 S(第63位) e((62位到52位)) m(51位到0位)

单精度浮点数和双精度浮点数都是用IEEE754标准定义的,其中有一些 约定

  1. 规格化的
    e!=0&e!=255
  2. 非规格化的
    e=0; 这里阶码E约定为固定值,E=1-Bias,(单精度时E=-126,双精度E=-1022);
  3. 无穷
    e=255 & m=0 ;阶码全为1,小数域全为0,根据符号位S来确定无穷大(s=0)还是无穷小(s=1)
  4. NaN(Not a Number,不是一个数)
    e=255 & m!=0;阶码全为1,小数域不为0
E用移码表示, 为了提供一种从非规格化值到规格化值平滑转换的方法 (为了规格化最小数和非规格化最大数平滑转变)

0X02 极限值说明

Console.WriteLine(float.MaxValue); // 3.402823E+38
Console.WriteLine(float.MinValue);  //-3.402823E+38
Console.WriteLine(float.Epsilon);    //  1.401298E-45
1.最大值

S位取0,E位最大值取255-1 = 254,因为255有特殊含义 254=(11111110)2,M尾数m为11111111111111111111111)2
二进制表示: 01111111011111111111111111111111

2.最小值

S位取1,E位最大值取255-1 = 254,因为255有特殊含义 254=(11111110)2,M尾数m为(11111111111111111111111)2
二进制表示: 11111111011111111111111111111111

3.最接近0的浮点数(+0)

这里就得用非规格数来表示了,符号位S取0,阶码E取0,M尾数m取最小值为(00000000000000000000001)2
二进制表示: 00000000000000000000000000000001
这里补充上代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace floatTest1
{
    class Program
    {

        /// <summary>
        /// 打印浮点数的二进制
        /// </summary>
        /// <param name="a"></param>
       unsafe static void FToB(float a)
        {
            float* p = &a;
            int b = *(int*)p;
            Console.WriteLine(Convert.ToString(b, 2));
        }

        /// <summary>
        /// 最大值
        /// </summary>
        unsafe static void DebugMaxFloat()
       {
           float b = 0f;
           int* p = (int*)&b;


           //这里是以符号位下标为0,先压入最高位,最后压入最低位
           for (int i = 0; i < 32; i++)
           {
               int bit = 1;
               //符号位 0
               if (i == 0)
               {
                   bit = 0;
               }
               //阶码 1-8
               else if (i >= 1 && i <= 8)
               {
                   //254的二进制是11111110,最后一位为0;
                   if (i == 8)
                   {
                       bit = 0;
                   }

               }
               //尾数 9-31
               else
               {
                   bit = 1;
               }

               *p = *p << 1;
               *p = *p ^ bit;
           }
           //*p =* p >> 1;
           FToB(b);
           Console.WriteLine("Max::::"+b); 
       }

        /// <summary>
        /// 最小值
        /// </summary>
        unsafe static void DebugMinFloat()
        {
            float b = 0f;
            int* p = (int*)&b;


            //这里是以符号位下标为0,先压入最高位,最后压入最低位
            for (int i = 0; i < 32; i++)
            {
                int bit = 1;
                //符号位 0
                if (i == 0)
                {
                    bit = 1;
                }
                //阶码 1-8
                else if (i >= 1 && i <= 8)
                {
                    //254的二进制是11111110,最后一位为0;
                    if (i == 8)
                    {
                        bit = 0;
                    }

                }
                //尾数 9-31
                else
                {
                    bit = 1;
                }

                *p = *p << 1;
                *p = *p ^ bit;
            }
            //*p =* p >> 1;
            FToB(b);
            Console.WriteLine("Min::::" + b);
        }

        /// <summary>
        /// 最接近于+0的数
        /// </summary>
        unsafe static void DebugEpsilonFloat()
        {
            float b = 0f;
            int* p = (int*)&b;


            //这里是以符号位下标为0,先压入最高位,最后压入最低位
            for (int i = 0; i < 32; i++)
            {
                int bit = 1;
                //符号位 0
                if (i == 0)
                {
                    bit = 0;
                }
                //阶码 1-8 
                else if (i >= 1 && i <= 8)
                {
                    //阶码取0,非规格化值,
                    bit = 0;
                }
                //尾数 9-31
                else
                {
                    //尾数取1;
                    if(i==31)
                    {
                        bit = 1;
                    }
                    else
                    {
                        bit = 0;
                    }
                }

                *p = *p << 1;
                *p = *p ^ bit;
            }
            //*p =* p >> 1;
            FToB(b);
            Console.WriteLine("Epsilon::::" + b);
        }
       unsafe static void Main(string[] args)
        {
            Console.WriteLine("Max="+float.MaxValue); // 3.402823E+38
            Console.WriteLine("Min=" + float.MinValue);  //-3.402823E+38
            Console.WriteLine("Epsilon=" + float.Epsilon);    //  1.401298E-45
            Console.WriteLine("------------------------------------------------------------------------------------");
            DebugMaxFloat();
            DebugMinFloat();
            DebugEpsilonFloat();
        }
    }
}

0X03 举例单精度浮点数的表示

1.整数位表示

以a = 8为例子,8的二进制1000=1*23,符号位S=0;E = 3+127=130=(10000010)2;M尾数1.m=1.0,m全是0;
所以表示出来为:
01000001000000000000000000000000

2.小数位表示

以a= 0.75为例子 0.75 = (1.1*2-1)2,符号位S=0;E = -1+127 = 126=(01111110)2;M尾数1.m=1.1,m=(10000000000000000000000)2 ;所以表示出来的数为:
00111111010000000000000000000000

3.带整数位和小数位的表示

以a=8.75为例子,8.75= (1000.11)2=(1.00011*23)2,符号位S=0;E= 3+127=130=(10000010)2;M尾数1.m=1.00011 , m=(00011000000000000000000)2;所以表示出来的数为:
01000001000011000000000000000000
上代码:

        /// <summary>
        /// 打印浮点数的二进制
        /// </summary>
        /// <param name="a"></param>
        unsafe static void FToB(float a)
        {
            float* p = &a;
            int b = *(int*)p;
            Console.WriteLine(Convert.ToString(b, 2));
        }

        unsafe static void Main(string[] args)
        {

            FToB(8f);
            FToB(0.75f);
            FToB(8.75f);
        }

结果:
结果

0X04 浮点数的运算

参考这篇文章:浮点数的表示和基本运算

文章参考:
浮点数的表示和基本运算
浮点型 float double
IEEE-754 Analysis
2.7.1 浮点加法和减法
2.7.2 浮点乘、除法运算
浮点加法、减法, 乘法、除法运算

猜你喜欢

转载自blog.csdn.net/codingriver/article/details/82888010