zoukankan      html  css  js  c++  java
  • 计算机系统导论——小班作业(2)——浮点数的位级表示

    2019年9月22日

     

    题目2.88

    答案

    格式A

    格式B

    1 01110 001

    -9/16

    1 0110 0010

    -9/16

    0 10110 101

    +208

    0 1110 1010

    +208

    1 00111 110

    -7/(2^10)

    1 0000 0111

    -7/(2^10)

    0 00000 101

    5/(2^17)

    0 0000 0000

    +0

    1 11011 000

    -2^12

    1 1111 0000

    -∞

    0 11000 100

    +768

    0 1111 0000

    +∞

     

     

     

    特殊要求

     

     

    题目2.94

    我的float_twice函数

     1 /* Access bit-level representation floating-point number*/
     2 typedef unsigned float_bits;
     3 
     4 /* Compute 2*f. If f is NaN, then return f.*/
     5 float_bits float_twice(float_bits f){
     6     /* Decompose bit representation into parts */
     7     unsigned sign = f&(1<<31);
     8     unsigned exp = f&(0xFF<<23);
     9     unsigned frac = f&0x7FFFFF;
    10     // 特殊值:f = NaN or f = +-inf, 返回f本身
    11     if(exp == (0xFF<<23)) return f;
    12     // 非规格化:2.0*(float)f与2*(unsigned)f的低31位的位级表示一样
    13     else if(!exp) return sign | (frac<<1);
    14     // 最大的一些规格化:2.0*f溢出, 返回+-inf
    15     else if(exp == (0xFE<<23)) return sign | (0xFF<<23);
    16     // 其他的规格化:exp位+1
    17     else return sign | (exp+(1<<23)) | frac;
    18 }
    View Code

    我的测试函数 

     1 //测试函数
     2 void MyTestFunc(float f){
     3     //f = sqrt(-1); //本句用于测试f=NaN的情况
     4     //unsigned f3 = 0x7f400000; f = *(float*)&f3; //本句用于测试2.0*f溢出的情况
     5     float f2 = 2.0*f;
     6     float_bits _f = *(unsigned*)&f,
     7                _f2 = *(unsigned*)&f2,
     8                flt_f = float_twice(_f);
     9     printf("f = %f = 0x%.8x
    ", f, _f);
    10     printf("2.0*f = %f = 0x%.8x
    ", f2, _f2);
    11     printf("float_twice(f) = 0x%.8x
    ", flt_f);
    12     printf("(2.0*f == float_twice(f)) = %d
    
    ", _f2 == flt_f);
    13     return;
    14 }
    View Code

    完整程序代码 

     1 /*
     2  README:
     3  本程序用float_twice()函数按位操作实现浮点数*2.0的计算,并提供了测试函数MyTestFunc()。
     4  float_twice()函数的实现思路如下:
     5  1.将传入的浮点数f的二进制序列划分为:
     6     sign(仅保留符号位)、exp(仅保留23-30的阶码位)、frac(仅保留0-22的尾数位)三个部分;
     7  2.根据exp值的分类进行*2运算:
     8     (1)exp的8位全部为1——特殊值(f=NaN or f=+-inf), 返回f本身;
     9     (2)exp的8位全部为0——非规格化,2.0*(float)f与2*(unsigned)f的低31位的位级表示一样;
    10     (3)exp的8位为0xFE——最大的一些规格化:2.0*f溢出, 返回+-inf;
    11     (4)所有其他情况——其他的规格化:exp位+1;
    12  MyTestFunc()函数的功能如下:
    13  1.测试输入一般浮点数的运行结果;
    14  2.测试NaN的运行结果:需要在函数中运行“f = sqrt(-1);”这行代码;
    15  3.测试2.0*f溢出的情况:需要在函数中运行“unsigned f3 = 0x7f000000; f = *(float*)&f3;”这行代码,f3的取值范围为0x7f000000~0x7f7fffff.
    16  */
    17 #include <cstdio>
    18 #include <cmath>
    19 using namespace std;
    20 
    21 /* Access bit-level representation floating-point number*/
    22 typedef unsigned float_bits;
    23 
    24 /* Compute 2*f. If f is NaN, then return f.*/
    25 float_bits float_twice(float_bits f){
    26     /* Decompose bit representation into parts */
    27     unsigned sign = f&(1<<31);
    28     unsigned exp = f&(0xFF<<23);
    29     unsigned frac = f&0x7FFFFF;
    30     // 特殊值:f = NaN or f = +-inf, 返回f本身
    31     if(exp == (0xFF<<23)) return f;
    32     // 非规格化:2.0*(float)f与2*(unsigned)f的低31位的位级表示一样
    33     else if(!exp) return sign | (frac<<1);
    34     // 最大的一些规格化:2.0*f溢出, 返回+-inf
    35     else if(exp == (0xFE<<23)) return sign | (0xFF<<23);
    36     // 其他的规格化:exp位+1
    37     else return sign | (exp+(1<<23)) | frac;
    38 }
    39 
    40 //测试函数
    41 void MyTestFunc(float f){
    42     //f = sqrt(-1); //本句用于测试f=NaN的情况
    43     //unsigned f3 = 0x7f000000; f = *(float*)&f3; //本句用于测试2.0*f溢出的情况
    44     float f2 = 2.0*f;
    45     float_bits _f = *(unsigned*)&f,
    46                _f2 = *(unsigned*)&f2,
    47                flt_f = float_twice(_f);
    48     printf("f = %f = 0x%.8x
    ", f, _f);
    49     printf("2.0*f = %f = 0x%.8x
    ", f2, _f2);
    50     printf("float_twice(f) = 0x%.8x
    ", flt_f);
    51     printf("(2.0*f == float_twice(f)) = %d
    
    ", _f2 == flt_f);
    52     return;
    53 }
    54 
    55 int main() {
    56     float f;
    57     while(printf("please enter a float : ")){
    58         scanf("%f", &f);
    59         MyTestFunc(f);
    60     }
    61     return 0;
    62 }
    View Code

    测试结果(输入输出都放在一起啦)

    (1)f = NaN 

    please enter a float : 0
    f = nan = 0xffc00000
    2.0*f = nan = 0xffc00000
    float_twice(f) = 0xffc00000
    (2.0*f == float_twice(f)) = 1

    (2)2.0*f = +-inf (溢出) 

    please enter a float : 0
    f = 255211775190703847597530955573826158592.000000 = 0x7f400000
    2.0*f = inf = 0x7f800000
    float_twice(f) = 0x7f800000
    (2.0*f == float_twice(f)) = 1

    (3)一般情况

    please enter a float : 0
    f = 0.000000 = 0x00000000
    2.0*f = 0.000000 = 0x00000000
    float_twice(f) = 0x00000000
    (2.0*f == float_twice(f)) = 1
    
    please enter a float : 9999999999999999999999999999999999999999
    f = inf = 0x7f800000
    2.0*f = inf = 0x7f800000
    float_twice(f) = 0x7f800000
    (2.0*f == float_twice(f)) = 1
    
    please enter a float : -302.34
    f = -302.339996 = 0xc3972b85
    2.0*f = -604.679993 = 0xc4172b85
    float_twice(f) = 0xc4172b85
    (2.0*f == float_twice(f)) = 1
    

     

     

      

    题目2.97

    我的float_i2f()函数

     1 /* Access bit-level representation floating-point number*/
     2 typedef unsigned float_bits;
     3 
     4 /* Compute Exponent, the highest bit with value 1*/
     5 int ComExp(unsigned i){
     6     for(int E=31; E>=0; --E)
     7         if(i & (1<<E))
     8             return E;
     9     printf("something wrong with cal_E()
    ");
    10     return -1; //abs = 0
    11 }
    12 
    13 /* Compute Fraction, with rounding to even*/
    14 unsigned ComFrac(unsigned i, unsigned E){
    15     i = i&((1<<E)-1);//delete highest bit with value 1
    16     //no rounding
    17     if(E <= 23)
    18         return i<<(23-E);
    19     //with rounding
    20     else{
    21         bool guard_bit = (i>>(E-23))&1,
    22         round_bit = (i>>(E-24))&1,
    23         sticky_bit = E>24 && (i&((1<<(E-24))-1));
    24         //round up: >0.5
    25         if(round_bit && sticky_bit) return (i>>(E-23))+1;
    26         //round to even: =0.5
    27         if(round_bit && !sticky_bit && guard_bit) return (i>>(E-23))+1;
    28         //round down: =0.5 or <0.5
    29         return i>>(E-23);
    30     }
    31 }
    32 
    33 /* Compute (float)i*/
    34 float_bits float_i2f(int i){
    35     //i == 0
    36     if(!i) return 0;
    37     //i != 0
    38     unsigned sign = i & (1<<31);//sign bit
    39     unsigned iabs = sign ? -i : i;//absolute value of i
    40     int E = ComExp(iabs);//exponent
    41     unsigned exp = (E + 127) << 23;//exponent bits
    42     unsigned frac = ComFrac(iabs, E);//fraction bits
    43     //rounding makes exp++
    44     if(frac & (1<<23)){
    45         frac = 0;
    46         exp += 1<<23;
    47     }
    48     return sign | exp | frac;
    49 }
    View Code

    我的测试函数

     1 //测试函数
     2 void MyTestFunc(int i){
     3     float f = (float)i;
     4     float_bits _f = *(unsigned*)&f, flt_f = float_i2f(i);
     5     printf("i = %d = 0x%.8x
    ", i, i);
     6     printf("(float)i = %f = 0x%.8x
    ", f, _f);
     7     printf("float_i2f(i) = 0x%.8x
    ", flt_f);
     8     printf("(float)i == float_i2f(i) = %d
    
    ", _f == flt_f);
     9     return;
    10 }
    View Code

    完整程序代码 

     1 /*
     2  谭世茵
     3  1800017827
     4  2019年9月22日
     5  《深入理解计算机系统》课后习题2.97
     6  
     7  README:
     8  本程序用float_i2f()函数通过位操作实现int到float型变量的转换,并提供了测试函数MyTestFunc()。
     9  float_i2t()函数需要另外几个函数的辅助,避免混乱和冗杂:
    10  1.ComExp()函数:确定阶码exp的值,即寻找unsigned int最高非零位;
    11  2.ComFrac()函数:确定尾数位frac的值,包括左右移位和利用GRS实现尾数的舍入。
    12  float_i2t()函数实现思路如下:
    13  1.传入的i=0,直接返回0;
    14  2.传入的i!=0,则分别确定i的sign、exp、frac位的值(利用ComExp()和ComFrac()函数);
    15  若在ComFrac()函数中发生连续进位导致frac的第23位变为1,则exp需要增加1,frac需要变为0;
    16  3.合并sign、exp、frac位,并返回。
    17  MyTestFunc()函数的操作指示详见代码注释。
    18  
    19  */
    20 #include <cstdio>
    21 using namespace std;
    22 
    23 /* Access bit-level representation floating-point number*/
    24 typedef unsigned float_bits;
    25 
    26 /* Compute Exponent, the highest bit with value 1*/
    27 int ComExp(unsigned i){
    28     for(int E=31; E>=0; --E)
    29         if(i & (1<<E))
    30             return E;
    31     printf("something wrong with cal_E()
    ");
    32     return -1; //abs = 0
    33 }
    34 
    35 /* Compute Fraction, with rounding to even*/
    36 unsigned ComFrac(unsigned i, unsigned E){
    37     i = i&((1<<E)-1);//delete highest bit with value 1
    38     //no rounding
    39     if(E <= 23)
    40         return i<<(23-E);
    41     //with rounding
    42     else{
    43         bool guard_bit = (i>>(E-23))&1,
    44         round_bit = (i>>(E-24))&1,
    45         sticky_bit = E>24 && (i&((1<<(E-24))-1));
    46         //round up: >0.5
    47         if(round_bit && sticky_bit) return (i>>(E-23))+1;
    48         //round to even: =0.5
    49         if(round_bit && !sticky_bit && guard_bit) return (i>>(E-23))+1;
    50         //round down: =0.5 or <0.5
    51         return i>>(E-23);
    52     }
    53 }
    54 
    55 /* Compute (float)i*/
    56 float_bits float_i2f(int i){
    57     //i == 0
    58     if(!i) return 0;
    59     //i != 0
    60     unsigned sign = i & (1<<31);//sign bit
    61     unsigned iabs = sign ? -i : i;//absolute value of i
    62     int E = ComExp(iabs);//exponent
    63     unsigned exp = (E + 127) << 23;//exponent bits
    64     unsigned frac = ComFrac(iabs, E);//fraction bits
    65     //rounding makes exp++
    66     if(frac & (1<<23)){
    67         frac = 0;
    68         exp += 1<<23;
    69     }
    70     return sign | exp | frac;
    71 }
    72 
    73 //测试函数
    74 void MyTestFunc(int i){
    75     float f = (float)i;
    76     float_bits _f = *(unsigned*)&f, flt_f = float_i2f(i);
    77     printf("i = %d = 0x%.8x
    ", i, i);
    78     printf("(float)i = %f = 0x%.8x
    ", f, _f);
    79     printf("float_i2f(i) = 0x%.8x
    ", flt_f);
    80     printf("(float)i == float_i2f(i) = %d
    
    ", _f == flt_f);
    81     return;
    82 }
    83 
    84 int main() {
    85     int i;
    86     while(printf("please enter an integer with hexadecimal notation : ")){
    87         scanf("%x", &i);
    88         MyTestFunc(i);
    89     }
    90     return 0;
    91 }
    View Code

    测试结果(输入输出都放在一起啦)

    please enter an integer with hexadecimal notation : 0
    i = 0 = 0x00000000
    (float)i = 0.000000 = 0x00000000
    float_i2f(i) = 0x00000000
    (float)i == float_i2f(i) = 1
    
    please enter an integer with hexadecimal notation : -1
    i = -1 = 0xffffffff
    (float)i = -1.000000 = 0xbf800000
    float_i2f(i) = 0xbf800000
    (float)i == float_i2f(i) = 1
    
    please enter an integer with hexadecimal notation : fffffff
    i = 268435455 = 0x0fffffff
    (float)i = 268435456.000000 = 0x4d800000
    float_i2f(i) = 0x4d800000
    (float)i == float_i2f(i) = 1
    
    please enter an integer with hexadecimal notation : 7fffffff
    i = 2147483647 = 0x7fffffff
    (float)i = 2147483648.000000 = 0x4f000000
    float_i2f(i) = 0x4f000000
    (float)i == float_i2f(i) = 1
    

     

    明天又是新的一周,一起加油w!

  • 相关阅读:
    winform控件库二次开发yy
    Oracle数据库表死锁和解锁
    集合去重筛选
    linux手动生成core dump
    HandlerSocket简介以及php使用handlersocket
    使用truss、strace或ltrace诊断软件的“疑难杂症”
    Sqlserver 2012 导出表数据为SQL脚本
    MySQL的索引为什么使用B+Tree
    计算机体系
    docker使用
  • 原文地址:https://www.cnblogs.com/tanshiyin-20001111/p/11566083.html
Copyright © 2011-2022 走看看