计算机系统导论——小班作业(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\n", f, _f); 10     printf("2.0*f = %f = 0x%.8x\n", f2, _f2); 11     printf("float_twice(f) = 0x%.8x\n", flt_f); 12     printf("(2.0*f == float_twice(f)) = %d\n\n", _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\n", f, _f);
49     printf("2.0*f = %f = 0x%.8x\n", f2, _f2);
50     printf("float_twice(f) = 0x%.8x\n", flt_f);
51     printf("(2.0*f == float_twice(f)) = %d\n\n", _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()\n");
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\n", i, i);
 6     printf("(float)i = %f = 0x%.8x\n", f, _f);
 7     printf("float_i2f(i) = 0x%.8x\n", flt_f);
 8     printf("(float)i == float_i2f(i) = %d\n\n", _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()\n");
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\n", i, i);
78     printf("(float)i = %f = 0x%.8x\n", f, _f);
79     printf("float_i2f(i) = 0x%.8x\n", flt_f);
80     printf("(float)i == float_i2f(i) = %d\n\n", _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!

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM