一. 整型(int
/unsigned int
)
1. 机器数
-
原码:由符号位(正数为0,负数为1)和真值绝对值(二进制)表示。
表示范围为 , 。
例如,以8 bit字长为例(下同), 。
注意, 。
-
反码:正数的反码与其原码相同;对于负数,其原码的符号位不变,数值位按位求反。
表示范围为 , 。
例如, 。
注意, 。 -
补码:正数的补码与其原码相同;负数的补码有两种计算方法:
- 方法一:负数的补码是其反码+1的结果,若有溢出,则舍弃溢出位。例如, 。
- 方法二:负数 的补码 。例如, 。
表示范围为 。
另外, ,
-
移码:由补码的符号位取反得到,即: (其中 )。例如 。
另外, 。
2. 整型数的表示方法
-
有符号整型数(
int
)的表示方法:在内存中以补码的形式存储(long
/short
等与之类似)。 -
无符号整型数(
unsigned int
)的表示方法:在内存中以无符号数的形式存储。
3. 整型数的计算
(1) 类型转换
int
与int
,或unsigned int
与unsigned int
之间进行运算,结果的类型不变;int
与unsigned int
之间进行运算,结果为unsigned int
,如下面代码中:
#include <iostream>
using namespace std;
int main()
{
int a = -2;
unsigned int b = 1;
cout << a + b << endl;
}
输出结果不为-1,而为4294967295(二进制的4个字节全为1),即说明-2在内存是以补码存储的(补码为1000 … 0010),与无符号的1(二进制0000 … 0001)相加,结果为1111 … 1111。
此外需要注意,若两个操作数均为int
型,则结果一定为int
型(如18*5/9结果为10)。
(2) 移位运算
左移1位可以实现×2操作,右移1位可以实现÷2操作。
进行移位运算时,符号位不变,只有数值位参与移位。若为正数,则左移(或右移)时,最高位(最低位)舍弃,最低位(最高位)空出,填补0;若为负数,则左移时空缺位填补0,右移时空缺位填补1。
例如:-10的补码为1111 0110,左移1位得1110 1100,真值为-20。
(3) 有关溢出
以unsigned int
型(32位)为例,其最大值为0xFFFFFFFF
(可通过printf("%x",UINT_MAX);
查得),若产生溢出,则系统默认对
取余。如:
unsigned int ui = 0xFFFFFFFF;
ui += 2;
cout << ui << endl;
结果为1。
二. 浮点型(float
/double
)
1. 浮点数的表示方法
(1) 一般表示形式
,其中 为尾数(小数,可正可负,且 ), 为尾数的基值(一般取2、8、16等), 为阶码(二进制整数)。
例如:
(2) 规格化
当 时, 为规格化数。
规格化形式( ) | 规格化形式( ) | 特点 | |
---|---|---|---|
真值 | |||
原码 | |||
补码 | 数符和第一位不同 |
如 符合规格化标准。
(3) IEEE754标准
在IEEE754标准中,float
型浮点数的表示方式为(32位):
符号位 | 阶码 | 尾数 |
---|---|---|
31(1位) | 30~23(8位) | 22 ~ 0(23位) |
其中:
-
符号位 ——0表示正数,1表示负数;
-
阶码 ——用移码表示,偏移量为127;
-
尾数 ——有效数字位(补码),由于 符合规格化标准,故整数部分的无需进行存储。
例如-125.5,符号位
;其绝对值二进制表示为
(这里6为十进制),故尾数
(舍去了整数部分1),补全23位得111 1011 0000 0000 0000 0000;阶码
,即1000 0101。
故-125.5在内存中表示为:1 10000101 11110110000000000000000。
通过以下程序可以得到验证:
#include <iostream>
using namespace std;
int main()
{
float a = -125.5;
char *p = (char *)&a;
printf("%d ",*p); // 输出结果:0
printf("%d ",*(p+1)); // 输出结果:0
printf("%d ",*(p+2)); // 输出结果:-5
printf("%d ",*(p+3)); // 输出结果:-62
}
也可以在debug模式中,在内存中输入地址&a
,查得存储的内容为(由低字节到高字节)00 00 FB C2
,即C2FB0000,从而得证。
double
型浮点数表示方式完全类似,只是变为64位,且阶码的偏移量变为1023:
符号位 | 阶码 | 尾数 |
---|---|---|
63(1位) | 62~52(11位) | 51 ~ 0(52位) |
(4) 浮点数的表示范围
设尾数有 位,阶码有 位,则:
- 最小负数: ;
- 最大负数: ;
- 最小正数: ;
- 最大正数: 。
小于最小负数和大于最大正数的范围,称为上溢区,此区域的浮点数视为溢出;在最大负数和最小正数之间的区域,称为下溢区,此区域的浮点数视为0。
2. 浮点数的计算
(1) 类型转换
浮点数运算时,两个操作数中只要有一个为浮点型(不论为float
型还是double
型),都转化为double
型进行运算,结果也为double
型。
(2) 浮点数加减运算
设两个浮点数 , ,计算 的步骤如下:
-
对阶:若阶差 ,则表明已经对齐;若不为0,则需要“小阶向大阶看齐”(以防止移位时最高位丢失):将小阶 补至大阶,尾数右移 位;
-
尾数相加;
-
规格化:例如, 的阶码为11,尾数为11.1001,则将尾数左规,变为1.0010,阶码降为10;当尾数出现 或 时,表示出现了溢出,应右规,阶码+1;
-
舍入:0舍1入法或末尾恒置1法;
-
溢出判断:见浮点数的表示范围。
(3) 浮点数的乘除运算
乘(除)运算只需要将尾数相乘(除),阶码相加(减)即可。
三. 字符型(char
)
1. 表示方法
在内存中,字符以ASCII码对应的整型数存储(8位)。
2. 计算方法
在计算时,不论char
还是unsigned char
型,均转换为int
型进行计算。