zoukankan      html  css  js  c++  java
  • <转载>浅谈C/C++的浮点数在内存中的存储方式

     C/C++浮点数在内存中的存储方式

           任何数据在内存中都是以二进制的形式存储的,例如一个short型数据1156,其二进制表示形式为00000100 10000100。则在Intel CPU架构的系统中,存放方式为  10000100(低地址单元) 00000100(高地址单元),因为Intel CPU的架构是小端模式。但是对于浮点数在内存是如何存储的?目前所有的C/C++编译器都是采用IEEE所制定的标准浮点格式,即二进制科学表示法。

           在二进制科学表示法中,S=M*2^N 主要由三部分构成:符号位+阶码(N)+尾数(M)。对于float型数据,其二进制有32位,其中符号位1位,阶码8位,尾数23位;对于double型数据,其二进制为64位,符号位1位,阶码11位,尾数52位。

                    31        30-23       22-0

    float       符号位     阶码        尾数

                    63        62-52       51-0

    double    符号位     阶码        尾数

    符号位:0表示正,1表示负

    阶码:这里阶码采用移码表示,对于float型数据其规定偏置量为127,阶码有正有负,对于8位二进制,则其表示范围为-128-127,double型规定为1023,其表示范围为-1024-1023。比如对于float型数据,若阶码的真实值为2,则加上127后为129,其阶码表示形式为10000010

    尾数:有效数字位,即部分二进制位(小数点后面的二进制位),因为规定M的整数部分恒为1,所以这个1就不进行存储了。

    下面举例说明:

    float型数据125.5转换为标准浮点格式

    125二进制表示形式为1111101,小数部分表示为二进制为 1,则125.5二进制表示为1111101.1,由于规定尾数的整数部分恒为1,则表示为1.1111011*2^6,阶码为6,加上127为133,则表示为10000101,而对于尾数将整数部分1去掉,为1111011,在其后面补0使其位数达到23位,则为11110110000000000000000

    则其二进制表示形式为

    0 10000101 11110110000000000000000,则在内存中存放方式为:

    00000000   低地址

    00000000

    11111011

    01000010   高地址

    而反过来若要根据二进制形式求算浮点数如0 10000101 11110110000000000000000

    由于符号为为0,则为正数。阶码为133-127=6,尾数为11110110000000000000000,则其真实尾数为1.1111011。所以其大小为

    1.1111011*2^6,将小数点右移6位,得到1111101.1,而1111101的十进制为125,0.1的十进制为1*2^(-1)=0.5,所以其大小为125.5。

    同理若将float型数据0.5转换为二进制形式

    0.5的二进制形式为0.1,由于规定正数部分必须为1,将小数点右移1位,则为1.0*2^(-1),其阶码为-1+127=126,表示为01111110,而尾数1.0去掉整数部分为0,补齐0到23位00000000000000000000000,则其二进制表示形式为

    0 01111110 00000000000000000000000

    由上分析可知float型数据最大表示范围为1.11111111111111111111111*2^127=3.4*10^38

    对于double型数据情况类似,只不过其阶码为11位,偏置量为1023,尾数为52位。

    测试程序:

    复制代码
    /*测试浮点型数据在内存中存放方式  2011.10.2*/ 

    #include <iostream>
    using namespace std;

    int main(int argc, char *argv[])
    {
    float a=125.5;
    char *p=(char *)&a;
    printf("%d ",*p);
    printf("%d ",*(p+1));
    printf("%d ",*(p+2));
    printf("%d ",*(p+3));
    return 0;
    }
    复制代码

    输出结果为:

    0

    0

    -5

    66

    在上面已经知道float型125.5在内存中存放方式为:

    00000000   低地址

    00000000

    11111011

    01000010   高地址

    因此对于p和p+1指向的单元,其中存储的二进制数表示的十进制整数为0;

    而对于p+2指向的单元,由于为char型指针,为带符号的数据类型,因此11111011,符号位为1,则为负数,由于在内存中二进制是以补码存储的,所以其真值为-5.

    对于p+3指向的单元,01000010,为正数,则其大小为66。上面程序输出结果验证了其正确性。

    作者:海子
             
    本博客中未标明转载的文章归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    使用 Dockerfile 定制镜像
    UVA 10298 Power Strings 字符串的幂(KMP,最小循环节)
    UVA 11090 Going in Cycle!! 环平均权值(bellman-ford,spfa,二分)
    LeetCode Best Time to Buy and Sell Stock 买卖股票的最佳时机 (DP)
    LeetCode Number of Islands 岛的数量(DFS,BFS)
    LeetCode Triangle 三角形(最短路)
    LeetCode Swap Nodes in Pairs 交换结点对(单链表)
    LeetCode Find Minimum in Rotated Sorted Array 旋转序列找最小值(二分查找)
    HDU 5312 Sequence (规律题)
    LeetCode Letter Combinations of a Phone Number 电话号码组合
  • 原文地址:https://www.cnblogs.com/xiaowenhu/p/3221203.html
Copyright © 2011-2022 走看看