一、补码讲解
1、定义
计算机的CPU无法进行减法操作,只能做加法操作。计算机做减法是通过CPU的加法器将其变为加法实现的。假设实现2-5
实际是2+(-5)
计算机用补码数表示负数,补码是对源码取反+1
计算机怎么实现-5?
在内存中5的二级制数为:
0000 0000 0000 0000 0000 0000 0000 0101
那么5的补码就是:
1111 1111 1111 1111 1111 1111 1111 1011
转成16进制就是:
ff ff ff fb
(低字节在前,高字节在后,原因是因为X86架构是小端存储)
计算机减法操作的实现方法
2的二进制数是
0000 0000 0000 0000 0000 0000 0000 0010
那么2-5就是用2的二级制数加上5的补码:
1111 1111 1111 1111 1111 1111 1111 1101
对于有符号数最高位是1就是负数,最高位是0就是正数
二、整型不同类型解析
1、整型的类型
整型包括6种类型
名称 | 表示 | 字节数 | 整型数取值 |
---|---|---|---|
有符号基本整型 | (signed) int | 4 | -231~(231-1) |
有符号短整型 | (signed) short | 2 | -215~(215-1) |
有符号长整型 | (signed) long | 8 | -231~(231-1) 或者 -263~(263-1) |
无符号基本整型 | (unsigned) int | 4 | 0~(232-1) |
无符号短整型 | (unsigned) short | 2 | 0~(216-1) |
无符号长整型 | (unsigned) long | 4 | 0~(232-1) |
有符号短整型最大值是32767,无符号短整型最大值时65535
有符号最高次位是符号位,无符号位最高次为是数值,那么
有符号短整型最大值就是:2^15-1
无符号短整型最大值就是:2^16-1
2、溢出解析
#include <stdio.h>
int main(){
int i=10;
short a=32767;
short b;
long c; // 32位程序是4个字节,68位程序是8字节
b=a+1; // 发生了溢出
i=a+1;
printf("-----------------------------\n");
unsigned int m=3;
unsigned short n=0x8056;
unsigned long k=5;
b=0x8056;
printf("b=%d\n",b);
printf("n=%d\n",n);
return 0;
}
- 代码执行到分割线时Debugger,发生溢出,b的结果是
-32768
,解决溢出的办法是用更大的空间来存。
- printf(“b=%d\n”,b); printf(“n=%d\n”,n); 分别输出:
b=-32682 n=32854
因为b
是有符号类所有输出负值
注意:无符号类用%d
是不严谨的,要用%u
三、浮点数IEEE754标准
float型变量占用4个字节,double型变量占用8个字节
- IEEE-754标准是:
S-符号位(占1位)E-指数部分(占8位)M-小数部分(占23位)
- IEEE-754标准规定:
符号位:0代表正数,1代表负数
指数部分:规定只能是1-254,不能全是0,不能全是1,指数部分运算前要减去127
小数部分:底数左边省略存储了一个1
格式 | SEEEEEEE | EMMMMMMM | MMMMMMMM | MMMMMMMM |
---|---|---|---|---|
二进制数 | 01000000 | 10010000 | 00000000 | 00000000 |
十六进制数 | 40 | 90 | 00 | 00 |
计算表格中的浮点数
S: 符号位 0 所以是正数
E: 1000 0001 转换为十进制数是 129,根据IEEE-754规定 减去 127 值为2,代表: 22
M: 0010 0000 0000 0000 0000 000 根据IEEE-754规定 1.001,十进制是 1+0.125=1.125
所以 E*M=4.5
例题练习:
结合下图计算1.456
解析
因为小端存储所以内存实际值是 0x3fba5e35
1.转换成二级制
格式 | SEEEEEEE | EMMMMMMM | MMMMMMMM | MMMMMMMM |
---|---|---|---|---|
二进制数 | 00111111 | 1 011 1010 | 0101 1110 | 0011 1011 |
十六进制数 | 3f | ba | 5e | 35 |
小数部分:011 1010 0101 1110 0011 1011,
根据IEEE-574规定,实际小数部分是 1.011 1010 0101 1110 0011 1011
20+2-2+2-3+24+26+…
得出结果为:1+0.25+0.125+0.0625+0.015625+…
指数部分:01111111 转成十进制 127 根据IEEE-574标准 减去 127 是 0
最后结果是 1.453125
四、浮点数精度丢失
类型 | 位数 | 数值范围 | 有效数字(精度) |
---|---|---|---|
float | 32 | 10-37~1038 或者 2-126~2127 | 6~7位(因为23位二进制来表示) |
double | 64 | 10-307~10308 或者 2-1022~21023 | 15~16为(因为52位的二进制来表示) |