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 }
我的测试函数
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 }
完整程序代码
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 }
测试结果(输入输出都放在一起啦)
(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 }
我的测试函数
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 }
完整程序代码
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 }
测试结果(输入输出都放在一起啦)
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!