CSAPP 浮点数位操作实验

浮点数操作实验


实验目的

深入理解浮点数的二进制表示及操作

实验内容

  • 本实验由一组浮点程序的实现问题构成

  • 规则参见bits.c中的“FLOATING POINT CODING RULES”

  • 允许的规则:

    • 使用条件语句和循环语句

    • 使用int和unsigned类型的变量和常量

    • 使用任意的算术、逻辑或是比较操作

  • 禁止的规则:

    • 定义或使用任意的宏

    • 定义额外的函数

    • 函数调用、类型转换

    • 使用除int和unsigned之外的数据类型,包括数列、结构体和联合体等

    • 使用浮点数相关的类型、操作或是常量

实验步骤

floatScale2

  1. 阶码的编码为e,尾数的小数部分为f,符号为s;
  2. 浮点数分三种情况:
    1. 规格化的:如果是e==254,返回正负无穷,否则返回x的阶码加1的值即可。
    2. 非规格化的:如为0,返回0。否则返回x的尾数乘以2的值。
    3. 无穷大和NaN:返回x的值。
uint32_t floatScale2(uint32_t x)
{
   uint32_t e = (x<<1)>>24;
   uint32_t f = (x<<9)>>9;
   uint32_t s = (x>>31)<<31;
   if(e!=0 && e!=255)
   {
      if(e==254)return s+((e+1)<<23);
      return s+((e+1)<<23)+f;
   }
   else if(e == 0)
   {
      if(f==0)return x;
      return s+(e<<23)+f*2;
   }
   else 
      return x;
}

floatFloat2Int

  1. 阶码的编码为e,尾数为f,符号为s;
  2. 浮点数分三种情况:
    1. 规格化的:阶码的值E为e-127,分两种情况:
      1. E>=0:转换为整数大于1,分两种情况:
        1. 正数:分三种情况:
          1. E<23:根据阶码扩大尾数不足23位,有23-E位舍去,将尾数左移(23-E)位,加上符号位返回。
          2. 23<=E<31:根据阶码能完全扩大尾数,且不会溢出,将尾数右移(E-23)位,加上符号位返回。
          3. E>=31:根据阶码扩大尾数发生溢出,返回0x80000000u
        2. 负数:和正数一样分为三种情况E<31,23<=E<31,E>31,不同的是符号s仅在最高位为1,有问题。根据f的位数为24-(23-E)=E+1或者(E-23)+24=E+1得到符号位应该是(0xffffffff<<(1+E))
      2. E<0:转换为整数小于1,返回0;
    2. 无穷大或NaN:返回0x80000000
    3. 非规格化的:远小于1,返回0。
uint32_t floatFloat2Int(uint32_t x)
{
   uint32_t e = (x<<1)>>24;
   uint32_t f = ((x<<9)>>9)+0x00800000;
   uint32_t s = (x>>31)<<31;
   if(e!=0 && e!=255)
   {
      int32_t E =e-127;
      uint32_t F1=(f>>(23-E));
      uint32_t F2=(f<<(E-23));
      if(E>=0)
      {
         if(s==0)
         {
            if(E<23)
               return s+F1;
            else if(E<31)
               return s+F2;
            return 0x80000000u;
         }     
         else
         {
            uint32_t t = (0xffffffff<<(1+E));
            if(E<23)
               return t+F1;
            else if(E<31)
               return t+F2;
            return 0x80000000u;
         }           
      }
      return 0;
   }
   if(e==255)
      return 0x80000000u;
   return 0;
}

floatPower2

  1. 单精度浮点数的规格化数精度为**-126~127**
  2. x<=-127,非规格化数,返回0。
  3. x>127,无穷大或NaN,返回0x7f800000
  4. -126<=x<=127,(x+127)为阶码E的对应编码,返回(x+127)<<23
uint32_t floatPower2(int32_t x)
{
   if(x<=-127)return 0;
   else if(x>127)return 0x7f800000; 
   return (x+127)<<23;
}

实验结果和探索

运行结果截图

实验结果

探索题目

上述题目如果限制为双精度浮点数,有何差别

答:在三个函数中,移位均不同。在floatScale2()中对E的情况判断的值为0和 2 11 2^{11} 211。在floatFloat2Int()函数中E在正数或者负数中判断情况为52位和63位。在floatPower2()中精度为 − 2 10 + 1 -2^{10}+1\quad 210+1 ~ 2 10 \quad 2^{10} 210

异常情况
  • 1/3的浮点数表示和误差分析:浮点表示为 1.01010101010101010101010 × 2 − 2 1.01010101010101010101010\times2^{-2} 1.01010101010101010101010×22,即00111110101010101010101010101010b,误差为 0.1010.... × 2 − 25 0.1010....\times2^{-25} 0.1010....×225

  • 无效情况。

  • 除以0:正或负 ∞ \infty (如果分子非零),或者NAN(如果分子为零)。

  • 阶码下溢:阶码下溢到无法用非规格化数表示,则结果为0。

  • 阶码上溢:阶码上溢,则结果溢出。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值