天天看點

深入了解計算機系統第二章家庭作業(2.91-2.96)

/***********2.91*************/
/*Compute |f|.   If f is NaN, then return f.*/
float_bits float_absval(float_bits f)
{
	unsigned sign = f >> 31;
	unsigned exp = (f >> 23) & 0xFF;
	unsigned frac = f &0x7FFFFF;

	if(exp == 255 && frac)
	{
		return (sign << 31) | (exp << 23) | frac;
	}

	return (exp << 23) | frac;
}
           
/*************2.92***************/
/*Compute -f. If f is NaN, then return f. */
float_bits float_negate(float_bits f)
{
	unsigned sign = f >> 31;
	unsigned exp = (f >> 23) & 0xFF;
	unsigned frac = f & 0x7FFFFF;

	if(exp == 0xFF && frac)
	{
		return f;
	}

	return ((~sign & 1) << 31) | (exp << 23) | frac;
}
           
/************2.93***************/
/*Compute 0.5*f. If f is NaN,then return f. */
float_bits float_half(float_bits f)
{
	unsigned sign = f >> 31;
	unsigned exp = (f >> 23) & 0xFF;
	unsigned frac = f & 0x7FFFFF;

	if(exp == 0xFF)
	{
		return f;
	}

	if(exp == 0)
	{
		if((frac & 0x03) == 0x03)
		{
			frac = (frac >> 1) + 1;
		}
		else
		{
			frac = (frac >> 1);
		}
		
	}

	else
	{
		exp--;
		if(exp == 0)
		{
			if((frac & 0x03) == 0x03)
			{
				frac = ((frac >> 1) + 1) + (1 << 22);
			}
			else
				frac = (frac >> 1) + (1 << 22);
			
		}
	}

	return (sign << 31) | (exp << 23) | frac;


}
           
/***********2.94************/
/* Compute 2*f. If f is NaN, then return f.  */
float_bits float_twice(float_bits f)
{
	unsigned sign = f >> 31;
	unsigned exp = (f >> 23) & 0xFF;
	unsigned frac = f & 0x7FFFFF;

	if(exp == 0xFF)
	{
		return f;
	}

	if(exp == 0)
	{
		if(frac & (1 << 22))
		{
			exp++;
			frac = (frac - (1 << 22)) << 1;
		}
		else
		{
			frac = frac << 1;
		}
	}

	else
	{
		exp++;
		if(exp == 0xFF)
		{
			frac = 0;
		}
	}

	return (sign << 31) | (exp << 23) | frac;
}
           
/*************2.95**************/
/* Compute (float) i */
float_bits float_i2f(int i)
{
	unsigned sign;
	unsigned exp;
	unsigned frac;

	int j;
	
	if(i == 0)
	{
		return (unsigned)i;
	}

	//小于零的話符号位置1,取-i進行操作

	if(i < 0)
	{
		i = ~i + 1;
		sign = 1;
	}

	else
	{
		sign = 0;
	}

	//判斷非零的最高位,從第0位開始計,j為最高非零位(不計符号位)
	for(j = 31;j > 0; --j)
	{
		if((0x01 << j) & i)
		{
			break;
		}
	}
	
	//階碼位比較容易确定
	exp = 127 + j;


	//沒有精度溢出時
	if(j <= 23)
	{
		frac = ((~(1 << j)) & i) << (23 - j);
	}

	//精度溢出時
	else
	{
		//舍棄
		if((((1 << (j - 23)) - 1) & i) < (1 << (j - 24)))
		{
			frac = ((~(1 << j)) & i) >> (j - 23);
		}
		//舍入
		else if((((1 << (j - 23)) - 1) & i) > (1 << (j - 24)))
		{
			frac = ((~(1 << j)) & i) >> (j - 23);
			frac = (frac + 1) & ~(1 << 23);
			if(frac == 0)
			{
				exp++;
			}
		}
		//向偶舍入
		else
		{
			frac = ((~(1 << j)) & i) >> (j - 23);
			if(frac & 0x01)
			{
				frac = (frac + 1) & ~(1 << 23);
				if(frac == 0)
				{
					exp++;
				}
			}
		}
		
	}
	
	return (sign << 31) | (exp << 23) | frac;
	
}
           
/************2.96**************/
/*
* Compute (int)f.
* If conversion causes overflow or f is NaN, return 0x80000000
*/
int float_f2i(float_bits f)
{
	unsigned sign = f >> 31;
	unsigned exp = (f >> 23) & 0xFF;
	unsigned frac = f & 0x7FFFFF;

	int result;

	if(exp <= 126)
		return 0;

	else if(exp > 126 && exp <= 150)
	{
		frac = frac >> (150 - exp);
		//如果是負數,要有一個取補碼的過程(關鍵一步),測試時可用0xc7ffffff測試
		if(sign)
		{
			result =((1 << 23) >> (150 - exp)) | frac;
			result = ~result + 1;
			return (sign << 31) | result;
		}
		else
			return (sign << 31) | ((1 << 23) >> (150 - exp)) | frac;
	}

	else if(exp > 150 && exp <= 157)
	{
		frac = frac << (exp - 150);
		//如果是負數,則取補碼,測試時可用0xcdffffff測試
		if(sign)
		{
			result = ((1 << 23) << (exp - 150)) | frac;
			result = ~result + 1;
			return (sign << 31) | result;
		}
		else		
			return (sign << 31) | ((1 << 23) << (exp - 150)) | frac;
	}
	else
	{
		return 0x80000000;
	}
}
           

繼續閱讀