飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 2838|回复: 6

[C/C++] 浮点数float和double内存存储方式解析学习_C++编程实现验证记录!!!

[复制链接]
  • TA的每日心情
    无聊
    2023-3-14 21:31
  • 签到天数: 74 天

    [LV.6]常住居民II

    发表于 2020-3-27 22:39:08 | 显示全部楼层 |阅读模式
    主要就是发个帖在PYG存档下学习记录:
    浮点数是学C那会的基础类型里最恐惧的东西,两年前硬着头皮把float的解析写了一下,
    代码渣的不行...
    如下:

    [C++] 纯文本查看 复制代码
    class float类
    {
     /*
     float浮点数在内存的存放方式: 
     bit 31  符号位 1位
     bit 30-23 指数位 8位
     bit 22-0 尾数位 23位
     */
    public:
     float类(float 参数) { 浮点数 = 参数; 初始化(); };
     void 设置浮点数(float 参数) { 浮点数 = 参数; 初始化(); };
     float 获取浮点数() { return 浮点数; };
     
     //如果是负数返回真,否则返回假
     bool 拆分浮点数(int *整数, float *小数) {
      
      int 整数位数 = 指数 - 127;
      int 位记录 = 22;
      *整数 = 0;
      *小数 = 0.0f;
      if (!整数位数)
      {
       *整数++;
      }
      else if (整数位数 > 0)
      {
       //整数
       *整数 += 指数运算(2, 整数位数);   
       for (int i = 整数位数; i > 0; i--)
       {
        二进制数 = *浮点指针 >> 位记录--;
        if (二进制数) { *整数 += 指数运算(2, i - 1); }
       }
       //小数
       for (int i = 位记录; i >= 0; i--)
       {
        二进制数 = *浮点指针 >> i;
        if (二进制数) { *小数 += 指数运算(2, -(位记录 - i + 1)); }
       }
      } 
      else
      {
       //整数为0的小数
       *小数 += 指数运算(2, 整数位数);
       for (int i = 位记录; i >= 0; i--)
       {
        二进制数 = *浮点指针 >> i;
        if (二进制数) { *小数 += 指数运算(2, -(位记录 - i - 整数位数 + 1)); }
       }
      } 
      return 符号;
     };
     
     //二进制位
     unsigned int 符号 : 1;
     unsigned int 指数 : 8;
     unsigned int 尾数1 : 1;
     unsigned int 尾数2 : 1;
     unsigned int 尾数3 : 1;
     unsigned int 尾数4 : 1;
     unsigned int 尾数5 : 1;
     unsigned int 尾数6 : 1;
     unsigned int 尾数7 : 1;
     unsigned int 尾数8 : 1;
     unsigned int 尾数9 : 1;
     unsigned int 尾数10 : 1;
     unsigned int 尾数11 : 1;
     unsigned int 尾数12 : 1;
     unsigned int 尾数13 : 1;
     unsigned int 尾数14 : 1;
     unsigned int 尾数15 : 1;
     unsigned int 尾数16 : 1;
     unsigned int 尾数17 : 1;
     unsigned int 尾数18 : 1;
     unsigned int 尾数19 : 1;
     unsigned int 尾数20 : 1;
     unsigned int 尾数21 : 1;
     unsigned int 尾数22 : 1;
     unsigned int 尾数23 : 1;
    private:
     float 浮点数;
     int *浮点指针 = (int *)&浮点数; 
     unsigned int 二进制数 : 1;
     float 指数运算(int 整数, int 指数)
     {
      int 指数绝对值; int 结果 = 整数;
      if (!整数) { return 0.0f; }
      if (!指数) { return 1.0f; }  
      指数 > 0 ? 指数绝对值 = 指数 : 指数绝对值 = -指数;
      if (指数绝对值 == 1) { return 指数 > 0 ? 结果 : 1.0f / 结果; }
      for (size_t i = 指数绝对值; i > 1; i--) { 结果 *= 整数; }
      return 指数 > 0 ? 结果 : 1.0f / 结果;
     }
     void 初始化()
     {  
      符号 = *浮点指针 >> 31;
      指数 = *浮点指针 >> 23;
      尾数1 = *浮点指针 >> 22;
      尾数2 = *浮点指针 >> 21;
      尾数3 = *浮点指针 >> 20;
      尾数4 = *浮点指针 >> 19;
      尾数5 = *浮点指针 >> 18;
      尾数6 = *浮点指针 >> 17;
      尾数7 = *浮点指针 >> 16;
      尾数8 = *浮点指针 >> 15;
      尾数9 = *浮点指针 >> 14;
      尾数10 = *浮点指针 >> 13;
      尾数11 = *浮点指针 >> 12;
      尾数12 = *浮点指针 >> 11;
      尾数13 = *浮点指针 >> 10;
      尾数14 = *浮点指针 >> 9;
      尾数15 = *浮点指针 >> 8;
      尾数16 = *浮点指针 >> 7;
      尾数17 = *浮点指针 >> 6;
      尾数18 = *浮点指针 >> 5;
      尾数19 = *浮点指针 >> 4;
      尾数20 = *浮点指针 >> 3;
      尾数21 = *浮点指针 >> 2;
      尾数22 = *浮点指针 >> 1;
      尾数23 = *浮点指针 >> 0;
     };
    };



    今天有网友提及,然后发了这个给他...
    然后聊到double,郁闷,跟float还略有不同,又折腾了一天,做个记录,发pyg存个
    代码如下:
    [C++] 纯文本查看 复制代码
     //如果是负数返回真,否则返回假_整数部分不能超过10位10进制数
    bool 浮点数拆分(double 浮点数, int* 整数, double* 小数)
    {
     //类型         符号位         指数位             尾数位
     //floa(32bit) 最左侧(第31位) 第30-23位(占8bit) 第22-0位(占23bit)
     //double(64bit) 最左侧(第63位) 第62-52位(占11bit) 第51-0位(占52bit)
     llong 浮点数据 = *(llong*)&浮点数;
     unsigned int 指数 = (浮点数据 >> 52) & 0x7FF;
     int 整数位数 = 指数 - 0x3FF;
     int 位记录 = 51;//0-52是位数51是最高位
     unsigned int 二进制数;
     int 位开始 = 0;
     //初始化
     *整数 = 0;
     *小数 = 0.0;
     //如果整数部分是0的话_不用进来了
     if (整数位数 >= 0)
     {
      *整数 += 1 << 整数位数;
      for (int i = 整数位数; i > 0; i--)
      {
       二进制数 = 浮点数据 >> 位记录--;
       if (二进制数 << 31) {
        *整数 += 1 << i - 1;
       }
      }
      整数位数 = 位记录 > 30 ? 30 : 位记录;
     }
     else
     {
      //整数部分为0的话_指数为负数
      //而这个负数刚好是开始计算的位置
      位开始 = -整数位数;
      *小数 += 1.0 / (1 << 位开始);
      整数位数 = 30 - 位开始;
     }
     //*小数 = 浮点数 - *整数;
     for (int i = 位开始; i <= 整数位数; i++)
     {
      二进制数 = 浮点数据 >> 位记录--;
      if (二进制数 << 31) { *小数 += 1.0 / (1 << (i + 1)); }
     }
     //小数精度16位
     //1.1234567891234568
     return 浮点数据 >> 63;
    }



    评分

    参与人数 1威望 +1 飘云币 +1 收起 理由
    不破不立 + 1 + 1

    查看全部评分

    PYG19周年生日快乐!
  • TA的每日心情
    开心
    5 小时前
  • 签到天数: 2211 天

    [LV.Master]伴坛终老

    发表于 2020-3-28 11:08:11 | 显示全部楼层
    坐沙发,学习,收藏备用。

    点评

    被我看到你的签名了…… 浪里个浪  发表于 2020-3-28 11:57
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2022-9-15 21:08
  • 签到天数: 176 天

    [LV.7]常住居民III

    发表于 2020-3-31 14:27:26 | 显示全部楼层
    什么版本VS支持中文函数名?
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2024-2-22 22:00
  • 签到天数: 326 天

    [LV.8]以坛为家I

    发表于 2020-4-1 21:46:46 | 显示全部楼层
    跟着一起学习啦&#128513;
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2020-8-24 10:20
  • 签到天数: 17 天

    [LV.4]偶尔看看III

    发表于 2020-4-19 22:08:59 | 显示全部楼层
    c语言是我抹不去的痛还是要努力学习去掌握它
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表