您的位置:首页 > 其它

利用位运算计算某种数据类型的最大值和最小值

2013-03-28 19:54 274 查看
常见数值的补码

数值
补码
0
0000 0000
1
0000 0001
-1
1111 1111
-256
1000 0000
255
0111 1111
最高位是符号位,0表示正数,1表示负数。

已知负数求补码

方法:将对应绝对值的补码按位取反,然后加上1,比如求-1的补码,先取1的补码:

0000 00011
按位取反1111 1110
加上11111 1111-1
已知负数的补码,求负数

方法:补码-1,然后按位取反得到绝对值,然后加上负号

1111 1111
减去11111 1110
按位取反0000 00011
加上负号-1
也可以直接按位取反,得到绝对值加上1,然后加上负号
1111 1111
按位取反0000 00000
加上11
填上负号-1
再如:

1000 0000
按位取反0111 1111127
加上1128
填上负号-128
最大值和最小值的特征

2550111 1111
-2561000 0000
327680111 1111 1111 1111
-327691000 0000 0000 0000
从以上补码,可以看出,任何一种数据类型,其最大值的特点是最高位为0,其余为均为1,而最小值,其特点是最高位为1,其余位均为0。因此对于任何一种数据类型,只要通过位移运算,得到符合上述特点的补码就可以获取到相应数据类型的最大值和最小值。现假设要计算短整型的数据范围,则其最大值和最小值的补码如下:

最大值0111 1111 1111 1111
最小值1000 0000 0000 0000
要获得以上补码,我们可以看到,最简单的是获得最小值的补码,它可以通过对1左移15位获得,而如果获得了最小值的补码,那么按位取反,就可以获得最大值的补码,过程如下:

0000 0000 0000 0001 1
左移15位1000 0000 0000 0000-32769
按位取反0111 1111 1111 111132768
下面是实验:

1<<(sizeof(int)*8-1)
-2147483648
~(1<<(sizeof(int)*8-1))
2147483647

注意以下差异:
(short)(1<<(sizeof(short)*8-1))
-32768
(short)(~(1<<(sizeof(short)*8-1)))
32767
((short)1)<<(sizeof(short)*8-1)
32768
~(((short)1)<<(sizeof(short)*8-1))
-32769

((int)1)<<(sizeof(int)*8-1)
-2147483648
~(((int)1)<<(sizeof(int)*8-1))
2147483647

((long)1)<<(sizeof(long)*8-1)
-2147483648
~(((long)1)<<(sizeof(long)*8-1))
2147483647


于是,对于一个对输入的整形数乘以一定倍数的模板函数,可以通过下面的方式确定数值范围:

template<typename T>
int Test(T x,int nScale)
{
	T nMin = (T)(1<<(sizeof(x)*8-1));		//确定该类型的最大值
	T nMax = (T)(~(1<<(sizeof(x)*8-1)));		//确定该类型的最小值
	int nVal = x*nScale;			//乘以一定的倍数
	if(nVal<nMin) return nMin;		//如果越下界,则返回下界值
	else if(nVal>nMax) return nMax;		//如果越上界,则返回上界值
	else return nVal;			//没有越界,返回乘倍后的值
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐