C语言中的整数类型及类型转换
有符号和无符号的数的转换
我们来看这一段程序
int main() { short x=-4321; unsigned short y=(unsigned short)x; printf("x=%d,y=%u",x,y); return 0; }
有符号数x是一个负数,而无符号数y的表示范围显然
不包括x的值,读者可以自己猜想一下这段程序的运行结果,再比较下面给出的运行结果
x=-4321,y=61215;
这样看没有一点关系,但将这两个数化为二进制表示时,我们就会发现其中的规律,如表2.5所示
观察可知,将short int 强制转换为unsigned short只改变数值,而两个变量对应的每位都是一样的。通过这个例子就知道,强制类型转换的结果保持位值不变,仅改变了解释这些位的方式
不同字长整数之间的转换
长整型转换为短整型
int main() { int x=165537,u=-34991; short y=(short)x,v=(short)u; printf("x=%d,y=%d\n",x,y); printf("u=%d.v=%d\n",u,v); }
结果:
x=165537,y=-31071
u=-34991,v=30545
十六进制表示为:x,y,u,v:0x000286a1,0x86a1,0xffff7751,0x7751,得出结论:
当大字长变量向小字长变量强制类型转换时,系统把多余的高位字长部分直接截断,低位直接赋值,因此也是一种保持位值得处理方法.
短整型变长整型
这里就不举例子了,直接说结果:
当大字长变量向小字长变量强制类型转换时,系统把多余的高位字长部分直接截断,低位直接赋值,因此也是一种保持位值得处理方法.
短整型变长整型
这里就不举例子了,直接说结果:
数据的存储和排列
数据的"大端方式"和"小端方式”存储
通常用最低有效字节(LSB)和最高有效字节(MSB)来分别表示数的低位和高位。例如,在32位计算机中,一个int型变量i的机器数位01 23 45 65H,其最高有效字节MSB=01H,最低有效字节LSB=67H
大端方式:就是将最高有效字节存放在前面;
小端方式:就是将最低有效字节存放在前面;
浮点数的表示与运算
浮点数的表示
定点数的局限性
我的财富:3540;2B定点整数short就可以表示
马云的财富:12345679....4B定点整数int就可以表示
如果换一种货币:1人民币=100000000000津巴布韦币用long型也表示不了
定点数表示的范围是很有限的,但我们又不能无限的增加长度
这就引出了浮点数
从科学计数法理解浮点数
普通计数法:+302657264576
科学计数法:+3.026*10^11=+11+3.026
阶码反映浮点数的表示范围及小数点的实际位置,
尾数M的数值部分的位数n反映了浮点数的精度
浮点数的表示
阶码:常用补码或移码表示的定点整数
尾数:常用原码或补码表示的定点小数
类比十进制:+302657264526=+3.026*10^11;
可以记位:+11+3.026
浮点数的真值:r^E*M;阶码的底一般为2
如果采用8比特存取空间:
这样b的最后一个数字就被舍弃掉了,这样表示的精度就降低了,那我们有没有方法让其不损失精度囊?
浮点数尾数的规格化
举个例子:+302657264526
可记为:+11+3.026
也可记为:+14+0.003(尾数的最高位是无效值,造成精度损失)
那么上面的那个b=2^2*(+0.01001)=2^1*(+0.10010)
规格化浮点数:规定尾数的最高数值位必须是一个有效值
左规:当浮点数运算的结果位非规格化时要进行规格化处理,将尾数算数左移一位,阶码减1;
右规:当浮点数运算的结果尾数出现溢出(双符号位为01或10)时,将尾数算数右移一位,阶码加1
例:a=010;00.1100,b=010;00.1000,求a+b
a=2^2*00.1100,b=2^2*00.1000
a+b=2^2*00.1100+2^2*00.1000
=2^2*(00.1100+00.1000)
=2^2*01.0100(发生了溢出)
右规=2^3*00.1010
注意:采用"双符号位",当溢出发生时,可以挽救。更高的符号位是正确的符号位
规格化浮点数的特点
1.用原码表示的尾数进行规格化:
正数为0.1*.....的形式,其最大值表示为0.11...1;最小值表示为0.10...0;
尾数的表示范围为1/2<=M<=(1-2^-n);
负数为1.1*....的形式,其最大值表示为1.10...0;最小值表示为1.11...1;
尾数的表示范围为-(1-2^-n)<=M<=-1/2;
2.用补码表示的尾数进行规格化:
正数为0.1*.....的形式,其最大值表示为0.11...1;最小值表示为0.10...0;
尾数的表示范围为1/2<=M<=(1-2^-n);
负数为1.0*...的形式,其最大值表示为1.01...1;最小值表示为1.00...0;
尾数表示范围:-1<=M<=-(1/2+2^-n);
浮点数标准IEEE754
移码
移码:补码的基础上将符号位取反,注意:移码只能用于表示整数
移码的定义:移码=真值+偏置值
此处8位移码的偏置=128D=1000 000B,即2^n-1
偏置值一般取2^n-1,此时移码=补码符号位取反
真值-127=-1111111B
移码=-1111111+10000000=0000 0001
真值-3=-11B
移码=-11+10000000=0111 1101
偏置值可以取其他值
令偏置值=127D=0111 1111B,即2^n-1 -1;
真值 -128=1000 0000B
移码=-1000 0000+0111 1111=1111 1111
IEEE 754标准
例题:
浮点数的运算
浮点数加减运算步骤: 9.85211*10^12+9.96007*10^10
1.对阶; 9.85211*10^12+0.0996007*10^12
思考为什么是小阶向大阶靠齐?将9.96化成0.0996而不是9.85转换成985?因为这样计算机内部这样处理很简单,方便对尾数进行处理
2.尾数加减; 9.951707*10^12
3.规格化; 如果尾数加减出现类似0.0099517*10^12时,需要左规;如果尾数加减出现类似99.517107*10^12时,需要右规
4.舍入; 若规定只能保证6为有效尾数,则
9.9517107*10^12->9.95171*10^12 (多余的直接砍掉)
或者,9.9517107*10^12->9.95172*10^12(若砍掉部分非0,则入1)
或者,也可以采用四舍五入的原则,当舍弃位>=5时,高位入1
5.判溢出 若规定阶码不能超过两位,则运算后阶码超出范围,则溢出 如:9.85211*10^99+9.96007*10^99=19.81218*10^99
规格化并用四舍五入的原则保留6位尾数,得1.98122*10^100
阶码超过两位,发生溢出
二进制浮点数的加减运算
浮点数的加减运算——舍入
强制类型转换
算术逻辑单元(ALU)
电路的基本原理,加法器设计
最基本的逻辑运算
优先级:与>或:AB+CD,先算与再算或
分配律:A(C+D)=AC+AD
结合律:ABC=A(BC)
结合律:A+B+C=A+(B+C)
这样设计有什么意义嘛?
Eg:实现AC+AD
根据分配律我们还可以这样设计
本质上逻辑表达式是对电路的数学化描述,简化逻辑表达式,就是在简化电路,就是在省钱。
用门电路求偶校验位
一位全加器
串行加法器
并行加法器
加法器,ALU的改进
根据前面的并行加法器可知,要算ci;就要计算AiBi+(Ai异或Bi)*Ci-1;那有没有方法去优化囊?更快的产生进位囊?
c0是一开始就知道的,这样就会减少计算成本.
并行加法器的优化
这里有点难理解,大家可以看我截的图,去b站看王道的课;
优点:各级进位信号同时形式,不需要重复计算,节省时间;
缺点:一直套娃,电路设计就会越来越复杂
为了避免这个缺点,我们四个为一组就可以了.
进行不断的套娃;
ALU芯片的优化