您的位置:首页 > 理论基础

深入理解计算机系统homework2 2.85 2.93 2.95

2013-09-20 12:49 148 查看
2.85
最小的正非规格化数
值:2^(-63) * (2^(2-2^15)) = 2^(-16445)
十进制值:

最小的正规格化数
值:1*2^(2-2^15) = 2^(-16382)
十进制值:

最大的规格化数:
值:(2-2^(-63))* 2^(2^14) = (2-2^(-63))*2^16384

2.93
【分析】
如果exp上全是1则该数是无穷大或者NaN,只需要异或一下判断全1即可。
否则如果exp大于0,那么我们在exp上减去一即可,但是如果exp被减成0了,因为exp不等于0,默认小数点前是1,那么我们就要把小数点前的1给补回去,然后做整体右移一位。如果exp原来是0,整体右移一位即可。
最后考虑向偶数进位,如果原数f末尾两位是11,则需要最后结果在尾数上加一。

float_bits float_half(float_bits f)
{
unsigned exp = f & 0x7F800000;//取出阶码
unsigned sign = f & 0x80000000;//取出符号位
unsigned frac = f & 0x7fffff;// 取出尾数
// 判断f的最后是否是3考虑向偶数进位
unsigned round = ( ( f >> 1 ) & f) & 1;
if (exp ^ 0x7F800000) // f不死NAN 或者 无穷大
{
if (exp)
{
exp = ( (exp >> 0x17) + ~0 ) << 0x17;//阶码减一
if ( ! exp ) frac = frac + (1 << 0x17 );
// 向后退1,正数前面默认为1.
}
if (!exp)
frac = ( frac >> 1 )+ round;
}
return sign | exp | frac;
}

2.95为了放在word中,缩进了一些代码【分析】将int转化成float,首先考虑符号位,然后讲i取绝对值,当成一个正数转化即可。然后判断i是2的几次幂,可以通过类似于二分法的方式判断。即右移16位判断是否不为0,如果不为0则exp+16,然后判断右移16位后剩余的位数有几位,否则右移8位判断依次类推。然后因为是正数,小数点左边存在一个隐式的1,所以num=( ~ (1<< exp ) ) & num ;把最高的1去掉,然后把剩余的数放进frac中,同时要考虑向偶数取整的问题。如果num不足23位,直接移动相应位数,放入frac中,否则截掉多余的位数,如果最后一位并且舍去一段中的最高也为1或者舍去的东西超过0.5那么就给frac+1,判断一下frac时候有溢出,溢出的话给exp+1,然后取剩余的23位的值即可。最后就是给exp加上bias偏置值,前提是如果num不为0。[code]float_bits float_i2f(int i)
{
unsigned sign = i >>0x1F;
unsigned num = i;
if (sign & 0x1)
num = ~num + 1; // 求绝对值
//printf("%x\n",num);
unsigned temp = num;
unsigned exp = 0;
unsigned frac = 0;
if(num >> 16) {
exp= exp + 0x10; num = num >> 0x10;//printf("%x%x\n",exp,num);
}

if(num>>8) {
exp= exp + 0x8; num = num >> 0x8;//printf("%x %x\n",exp,num);
}
if(num>>4) {
exp= exp + 0x4; num = num >> 0x4;//printf("%x %x\n",exp,num);
}
if(num>>2) {
exp= exp + 0x2; num = num >> 0x2;//printf("%x %x\n",exp,num);
}
if(num>>1) {
exp= exp + 0x1; num = num >> 0x1;//printf("%x %x\n",exp,num);
}
//正数小数点前的1需要去掉(即最高位的1去掉)
num = temp;
num=( ~ (1<< exp ) ) & num ;
//printf("num=%x\n",num);
if (temp >> 23) // 如果num超过了23位
{
unsigned delta = exp - 0x17;
frac = num >> delta;
//printf("%x %x\n",delta,frac);
unsigned round = 0;
int Cond1 = ( ( num & ((1 << delta) -1 ) ) > (1 << (delta-1)) );
int Cond2 = (frac & 0x1) && ( num >> (delta -1) & 0x1);
//printf("cond%d %d\n",Cond1,Cond2);
if( (exp != 0x17) & ( Cond1 | Cond2) )
// exp 不等于23 判断舍去后是否需要向偶数进位
{
round = 1;
frac = frac + round;
//printf("round-frac%x\n",frac);
if (frac >> 0x17)
{
exp +=1;
frac = frac & 0x7fffff;
}
}
//printf("frac=%x\n",frac);
} else
frac = num << (0x17 - exp ) ;
//printf("exp=%x\n",exp);
if (temp)
exp = exp + 127; // 加上bias偏置值
//printf("%x %x %x %x\n", num , sign,exp,frac);
return ( sign << 0x1F ) | ( exp << 0x17 ) | frac;

}

[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: