最近开始复习基础知识,发现才看到浮点数就一大堆疑问,上网搜了一大堆不是这个错就是那个错,上机一验证发现都有问题,干脆自己整理整理这方面知识,因为是用代码验证的,所以又涉及到与位操作符和移位操作符的内容。

  Visual C++中,float的32位这样分: 符号位(S):1位  阶码(E):8位  尾数(M):23位

  其中符号位就是正负号(float和double都是不能和unsigned合用的,所以一定有正负)。

  先介绍尾数,尾数是一个1.MMMMMMM……(23个M),所以尾数是一个>=1&&<=2的数的小数部分,翻译成尾数还是很恰当的。

  我们可以把小数看成 V=+/-  1.MMMMMMM……(23个M) * (2^E’) 这种形式,那阶码的意义就出来了,是2的幂次,因为有8位,所以能够表示[0,255],为了表示负数,这里采用移码方式(而不是整数中的补码方式,理由还没想清楚),即实际的2^E’的E’是阶码E-127,即范围变成[-127,128](很多资料上说[-128,127]是错误的),直观的说E'表示1.MMMMMMM……小数点的移位,正数则小数点向右移,负数小数点向左移。

  用一段输出float内存值的代码来验证下:

#include <iostream>
#include <string>
using namespace std;

int main(){
	float f = -3.0f;
	unsigned int* pa = (unsigned int*)(&f); 
	for(int i = 31;i >= 0;i--)
		cout << (*pa>>i &  0x01) << (i==31||i==23? "- ": "  "); 
	cout << "\n ";

	return 0;
}

 -3.0=- 1.1000000(一共22个0) * (2^1) (1.1在十进制中表示1.5,E'=1 得到E=128=10000000)

 

  写这段验证代码的时候顺便复习了下位与操作符(&)和移位操作符(<<  >>),以前完全没注意啊啊啊啊啊啊啊啊

(1)float、double、long double等类型不允许直接进行位与操作符啊,可用间接的方法变通,如float取地址(也是&符号)转换为unsigned int类型,再用取值操作符(*),这样编译器会以为是unsigned int类型。

(2)使用int、short、long移位时最好加上unsigned,这样就是汇编中逻辑移位(即全部移位),如果不加unsigned情况就较为复杂,正数全是逻辑移位,负数左移时保持符号位为1、右边补0,负数右移时保持符号位为1,左边补1,所以-1不管怎么右移都是-1。

(3)位与操作符就是将两个数进行与操作,&0x01就相当于掩码取出最后一位,其他位置成0

(4)位与操作符&的操作优先级小于移位操作符,但移位操作符小于取地址操作符&(取值操作符*),所以上面代码不会出错

posted on 2012-09-30 11:38  云 溪  阅读(5727)  评论(1编辑  收藏  举报