we choose to go to the moon!😉|

上山砍大树

园龄:5年3个月粉丝:13关注:3

2024-02-20 19:06阅读: 48评论: 0推荐: 0

csapp-homework-2.73

然后再看2.73这个题目:

Write code for a function with the following prototype:

/* Addition that saturates to TMin or TMax */
int saturating_add(int x, int y);

Instead of overflowing the way normal two’s-complement addition does, saturating
addition returns TMax when there would be positive overflow, and TMin
when there would be negative overflow. Saturating arithmetic is commonly used
in programs that perform digital signal processing.

Your function should follow the bit-level integer coding rules (page 164).

当程序运算有溢出的时候,返回对应的边界值(TMIN,TMAX),并且不能用判断循环等。看下答案怎么处理的这个情况:

/*
* saturating-add.c
*/
#include <stdio.h>
#include <assert.h>
#include <limits.h>
int saturating_add(int x, int y) {
int sum = x + y;
int sig_mask = INT_MIN;//0x80000000
/*
* if x > 0, y > 0 but sum < 0, it's a positive overflow
* if x < 0, y < 0 but sum >= 0, it's a negetive overflow
*/
int pos_over = !(x & sig_mask) && !(y & sig_mask) && (sum & sig_mask);
int neg_over = (x & sig_mask) && (y & sig_mask) && !(sum & sig_mask);
(pos_over && (sum = INT_MAX) || neg_over && (sum = INT_MIN));
return sum;
}
int main(int argc, char* argv[]) {
assert(INT_MAX == saturating_add(INT_MAX, 0x1234));
assert(INT_MIN == saturating_add(INT_MIN, -0x1234));
assert(0x11 + 0x22 == saturating_add(0x11, 0x22));
return 0;
}

这里有两个问题需要研究代码解决:

  1. 在没有条件判断符的情况下,如何判定正负溢出?
  2. 溢出后,怎么确定正负溢出然后返回对应的边界值?

首先分析在没有关系运算符的情况下,此函数如何判断正溢出的:

int pos_over = !(x & sig_mask) && !(y & sig_mask) && (sum & sig_mask);

当x & sig_mask == 0 ,y & sig_mask == 0且sum & sig_mask != 0的时候,这个正溢出标志pos_over等于1成立。下面逐一分析正溢出的这几个条件:

x & sig_mask == 0:只要x的最高位为0即可,这样对应的x的取值就去除了负数部分,此时x的取值范围为:x >= 0

y & sig_mask == 0:同理,y的最高位为0,y的取值范围为y >= 0

sum & sig_mask != 0:此时证明参数sum的最高位一定为1,此时sum的取值范围为:sum < 0

所以结合注释,可以得到问题1的答案。由原来需要关系运算符(>和<)if x > 0, y > 0 but sum < 0, it's a positive overflow,到现在直接利用二进制补码的特性——即最高位是否为1,和逻辑运算符&&的短路特性,来判断x、y和sum是正数还是负数,从而得到相同的溢出判断结果。

既然正溢出可以用逻辑运算与&&和位运算符&来获得,那么负溢出的分析也是相同的,这里就不再赘述。

然后就是分析溢出后,怎么确定正负溢出然后返回对应的边界值的问题。这里放下答案中对于这个问题处理的代码:

(pos_over && (sum = INT_MAX) || neg_over && (sum = INT_MIN));

这里还是利用了逻辑运算与&&的短路特性:如果正溢出,则执行sum = INT_MAX;如果负溢出,则执行sum = INT_MIN

本文作者:上山砍大树

本文链接:https://www.cnblogs.com/shangshankandashu/articles/18023850

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   上山砍大树  阅读(48)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起