《深入了解计算机系统》,家庭作业2.73、2.74

2.73

写出具有以下原型的函数代码:
/*Addition that saturates toTMin or TMax */
int saturating_add(int x, int y);
同正常的补码加法的溢出的方式不同,当正溢出时,饱和加法返回TMax,负溢出时,返回TMIn,饱和运算常常用在执行数字信号处理的程序中。
你的函数应该遵循位级整数编码规则。

先捋一捋需求:

1、若发生正溢出:返回TMax
2、若发生正溢出:返回TMin
3、题目虽然没说(或者我理解有误),但若没有发生溢出时也应该有个返回值,返回0;

再捋一捋规律:

1、补码相加发生正溢出时,两个参数一定都大于0
2、补码相加发生负溢出时,两个参数一定都小于0
3、判断溢出的方法是,当两个参数的符号符合溢出条件时,检测其相加的结果符号是否发生改变;

再捋一捋思路:

为了方便描述,定义一个参数:int result = x + y ;
1、规律1和2是发生溢出的必要条件,可以通过算术右移的操作生成只保留符号信息的二进制码——0x0(全0)或全1,然后将两个参数的符号信息按位异或(XOR),若符号相同(即满足了发生溢出的条件),异或操作后生成的二进制码会是0x0;到这里,再对结果取非,因为发生溢出的条件是溢出的必要条件(好废话啊= =!),这是为了让这个二进制码能通过按位与的操作左右最终的结果。
2、规律3是发生溢出的另一个条件,随便取一个参数,同样通过算术右移的操作只保留符号信息,然后对result同样进行算术右移的操作以获取符号信息,再将结果按位异或(XOR),若符号发生改变,会返回全1。
3、根据result的符号信息决定返回TMin还是TMax,我的思路是用result的符号信息(全0或全1)减去TMin,发生溢出时有以下几种情况:

溢出的情况result算术右移后的结果我想要的结果result符号信息减去TMin
正溢出全1TMax(最高位是0,其余全1)TMax
负溢出全0TMin(最高位是1,其余全0)TMin

可以看到通过符号信息二进制码减去TMin的操作可以得到预期的结果
4、将1、2、3的结果相与,得到最终的返回值;

OK,废话完毕,Talk is cheap,Show me the code:
int saturating_add(int x,int y){
	int result = x+y;//定义变量result,存储x+y的结果
	int bias =(sizeof(int)<<3)-1;//获取算术右移的偏移量
	int condition1 = ~(x>>bias^y>>bias);//定义变量condtion,存储发生溢出的必要条件(思路1、规律1、2)
	int result_signed = result>>bias;//同样只保留符号信息
	int condition2 = result_signed^(x>>bias);//与任意一个参数相异或,若result是发生溢出的结果,则得到全1的二进制码
	int TMin = 0x1<<bias;//通过左移位操作得到TMin
	int result_overflow = result_signed-TMin;//思路3
	return result_overflow & condition1 & condition2;//三个结果相与,得到最终结果		
}
测试代码

(为了偷懒,我把所有家庭作业写进了同一个源文件,测试的时候用的同一个main()函数,所以我直接贴图了):
1、两正相加不溢出
两正相加不溢出
2、两负相加不溢出
两负相加不溢出
3、负溢出
负溢出
4、正溢出
正溢出

2.74

写出具有以下原型的函数代码:
/Determine whether arguments can be subtracted without
overflow
/
int tsub_ok(int x,int y);
如果计算x-y不溢出,这个函数就返回1。

需求:

1、两个参数相减,不溢出返回1.

规律:

1、两个参数相减,符号不同一定不溢出
2、两个参数相减,溢出的结果符号一定改变
3、负数被减只能正溢出,正数被减只能负溢出

思路:

1、参照2.73的经验,同样对参数进行算术右移只保留符号信息,然后相异或,只有异或的结果若为0,才满足溢出的条件,所以再对异或的结果取非,最后的二进制码为全1的时候才满足溢出的条件
2、根据思路3,对相减的结果result进行同样的算术右移操作,然后对被减数y也进行同样的算术右移操作,保留符号位,两者相异或,若返回0,则说明发生了溢出。

x的符号y的符号result的符号溢出/不溢出
110或1不溢出
101不溢出
100负溢出
011正溢出
010不溢出
000或1不溢出
The code:
int tsub_ok(int x,int y){
	int result =x-y;
	int bias = (sizeof(int)<<3)-1;
	x = x >> bias;
	y = y >> bias;
	result = result >> bias;
	int condition1 = x^y;//若值为全1,才可能发生溢出
	int condition2 = ~(result ^ y);//溢出值为全1,不溢出返回0;
	return (condition1&condition2)==0;//两个条件有一个不满足,就判定没有发生溢出。
}
测试代码

1、最极端的情况,TMin-TMin:

在这里插入图片描述
2、两正相减(一定不溢出):
在这里插入图片描述
3、两负相减(一定不溢出):
在这里插入图片描述
4、正负相减(结果预期:不溢出/溢出):
在这里插入图片描述
在这里插入图片描述
5、负正相减(结果预期:(不溢出/溢出)):
在这里插入图片描述
在这里插入图片描述
踩坑:做2.74的时候,我的第一个方案是直接对y取负值(即令y = - y;),然后再与x相加(result = x+y;),就可以套用2.73的部分代码来操作,但是当y值为TMin时,没有对应的-y,所以行不通.
这是我写的第一篇博客,一个人看书敲代码很无聊,所以试着把学习的心得写成博客分享出来。
最后,本人非相关专业从业者,代码与思路有拖沓冗余之处,请多多指教,感激不尽。

用MATLAB计算波动率,股票历史价格为3.64 3.61 3.58 3.6 3.59 3.57 3.58 3.6 3.57 3.52 3.49 3.48 3.45 3.43 3.46 3.47 3.49 3.54 3.53 3.5 3.52 3.55 3.42 3.42 3.43 3.44 3.39 3.38 3.41 3.42 3.37 3.44 3.4 3.42 3.41 3.42 3.42 3.39 3.26 3.16 3.18 3.21 3.16 3.24 3.25 3.26 3.26 3.23 3.27 3.32 3.3 3.26 3.25 3.26 3.18 3.22 3.18 3.11 3.14 3.18 3.2 3.13 3.16 3.15 3.14 3.21 3.2 3.21 3.25 3.28 3.25 3.24 3.29 3.28 3.23 3.19 3.17 3.2 3.16 3.16 3.19 3.25 3.25 3.25 3.23 3.3 3.31 3.3 3.33 3.31 3.33 3.27 3.29 3.29 3.31 3.35 3.35 3.33 3.29 3.29 3.3 3.29 3.25 3.22 3.24 3.24 3.23 3.22 3.21 3.28 3.26 3.26 3.26 3.24 3.21 3.25 3.25 3.26 3.27 3.25 3.22 3.18 3.16 3.18 3.19 3.21 3.22 3.25 3.3 3.35 3.35 3.35 3.34 3.3 3.32 3.27 3.24 3.26 3.24 3.28 3.27 3.27 3.29 3.22 3.25 3.26 3.25 3.24 3.19 3.21 3.22 3.2 3.22 3.17 3.12 3.13 3.17 3.17 3.21 3.21 3.19 3.13 3.14 3.11 3.04 3.1 3.1 3.12 3.13 3.12 3.09 3.1 3.12 3.12 3.14 3.13 3.08 3.1 3.04 3.06 3.06 3.11 3.09 3.08 3.05 2.95 2.91 2.89 2.91 2.92 2.83 2.69 2.81 2.86 2.89 2.87 2.88 2.9 2.88 2.84 2.84 2.82 2.9 2.88 2.92 2.91 2.88 2.91 2.83 2.88 2.87 2.91 2.91 2.87 2.84 2.82 2.78 2.8 2.66 2.66 2.71 2.75 2.79 2.78 2.7 2.68 2.7 2.72 2.7 2.73 2.7 2.74 2.73 2.73 2.79 2.76 2.72 2.72 2.72 2.74 2.76 2.79 2.78 2.78 2.81 2.83 2.86 2.85 2.89 2.84 2.87 2.91 2.89 2.93 2.92 2.93 2.9 2.94 2.98 3.02 3.04 3.02 3.07 3.06 3.06 3.06 3.01 3 3.01 2.96 2.94 2.93 2.91 2.87 2.91 2.9 2.91 2.87 2.89 2.88 2.89 2.87 2.87 2.83 2.82 2.77 2.75 2.78 2.82 2.8 2.8 2.77 2.83 2.84 2.82 2.81 2.82 2.8 2.79 2.79 2.77 2.75 2.79 2.79 2.77 2.77 2.8 2.78 2.75 2.74 2.76 2.75 2.75 2.8 2.81 2.79 2.78 2.72 2.72 2.71 2.69 2.67 2.67 2.65 2.68 2.65 2.65 2.65 2.59 2.58 2.59 2.56 2.63 2.62 2.61 2.56 2.54 2.53 2.44 2.43 2.44 2.42 2.37 2.33 2.44 2.46 2.42 2.51 2.52 2.5 2.48 2.48 2.56 2.58 2.63 2.62 2.6 2.59 2.56 2.57 2.58 2.56 2.59 2.54 2.65 2.64 2.63 2.62 2.68 2.69 2.67 2.68 2.71 2.68 2.68 2.7 2.68 2.69 2.65 2.61 2.61 2.63 2.62 2.61 2.64 2.65 2.63 2.65 2.65 2.66 2.71 2.72 2.75 2.74 2.75 2.75 2.8 2.85 2.84 2.82 2.83 2.85 2.85 2.82 2.83 2.82 2.78 2.74 2.75 2.74 2.77 2.76 2.78 2.79 2.76 2.75 2.72 2.8 2.81 2.78 2.77 2.74 2.73 2.75 2.78 2.78 2.78 2.75 2.72 2.7 2.68 2.64 2.67 2.65 2.65 2.63 2.64 2.62 2.65 2.66 2.67 2.66 2.64 2.64 2.64 2.67 2.67 2.67 2.68 2.67 2.69 2.69 2.68 2.67 2.67 2.68 2.74 2.75 2.72 2.71 2.66 2.62 2.62 2.62 2.66 2.68 2.69 2.69 2.72 2.71 2.67 2.67 2.63 2.68 2.67 2.65 2.64 2.63 2.66 2.62 2.58 2.57 2.56 2.55 2.54 2.5 2.51
06-10
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值