csapp page124. practice problem 2.35

/* Determine whether arguments can be multiplied without overflow */
int tmult_ok(int x, int y){
int p = x*y;
/* Either x is zero, or dividing p by x gives y */
return !x || p/x == y;
}

函数 tmult_ok 的功能是检查两个二补数相乘会不会溢出, 逻辑是,要么 x 为零, 或者 乘积 p 除以 x 等于另一个乘数 y 的话,就说明不会溢出。

这题要求给出这个函数正确性的数学证明。首先证明当x=0这个情况的正确性。然后考虑w位的数字(w不等于0) 有 y, p, 和 q, 其中 p 是x, y执行了二补码乘法后的结果, q 是 p/x 的值。

书中给出三条线索,分别给出这三条线索的证明即可证明这个函数的正确性。

  1. 证明: x和y的整数相乘结果可以被写成 \(x*y = p + t*2^w\) 形式, 当且仅当 t != 0 的时候,p溢出。
  2. 证明: p 可以被写成 \(p = x * q + r\), 其中\(|r| < |x|\).
  3. 证明: 当且仅当 \(r = t = 0\) 的时候 \(q = y\).

答案是这么证明的:

1.因为x,y都是w位二补码表示的数,所以他们的乘积最多要用2w位表示,因为:

\(-2^{w-1} <= x, y <=2^{w-1} - 1\) 注:这是二补码的取值范围

所以 x*y 就要   大于等于 \(-2^{w-1} * (2^{w-1} - 1)\) 就等于 \(-2^{2*w - 1} + 2^{w - 1}\) 注: 其实就是Tmax*Tmin
                     小于等于 \((-2^{w - 1})^2\) 就等于 \(2^{2*w - 2}\) 注: 其实就是Tmin*Tmin,可以证明Tmax^2 没有 Tmin^2大

看见2的次方数是2w起跳的,就说明肯定得要2w位才能表示了。所以 x*y 理应是要用 2w 位表示的(但是2w位是溢出的,暂时不管),现在设 u 等于该乘积低w位的无符号形式,v 等于该乘积高w位的二补码形式。
那么,根据公式2.3 即二进制到二补码的转换公式可以得出 \(x*y = v*2^w + u\) 这个式子乍一看匪夷所思,怎么能把一个位向量劈成两半,前w位按二补码算然后乘以\(2^w\) ,后w位按无符号算然后两个部分加起来怎么刚好就是x和y的乘积??
其实只要根据二进制转二补码的公式细心推倒,马上就可以证明这个结论:

我们还知道 \(u = T2U_{2w}(p)\) 这里p是二补码乘积,因为实际上不管乘积结果有没有溢出,unsigned形式和tow's complement形式的乘积在w位上是一模一样的,这点在数的2.18给出了证明。
所以根据公式T2U 得 \(u = p_{w-1} * 2^w + p\), 把u 带入之前的 \(x*y = v*2^w + u\) 这里, 化简可以得到: \(x*y = 2^w * (v + p_{w-1}) + p\), 此时我们设 \(t = v + p_{w-1}\),公式变为:\(x*y = t* 2^w + p\)

这里我们就可以看出,当且仅当 t = 0 的时候, x*y 才等于p,t 不等于 0 的时候乘积是溢出的。到这里证明了上面的第1条。

2.因为无论 x*y 的值 p 有没有溢出,总之它是个整数,那么只要 p 是个整数,它除以一个非零整数 x 必然会得到一个商(q)和一个余数(r) 使得 \(p = x * q + r\) 其中 |r| < |x|
这里取绝对值是因为r 和 x 的符号可能不一样,比如 -7 / 2 得 -3 余 -1, |-1| < |2|。 这里证明了第2条。

3. 如果 q = y 根据 \(p = x*q+r\) 得出 \(p = x*y+r\) 其中 \(x*y = t * 2^w + p\) 所以 \(p = t*2^w + p + r\), 两边消去 p 以后得到 \(t*2^w = -r\) 要让这个等式成立,有两种情况,要么等号两边值相等,要么两边都为零。
在第2条的证明中,我们得出 |r| < |x|, 而x是二补码,所以绝对值的最大值是 2^w 所以 |r| < \(2^w\), 回到这里,等式左边出现了\(2^w\) 而 r 要比\(2^w\) 小,可见其值必不相等,则必须是为零的情况。所以必须 r = t = 0

根据第1条证明,我们知道要想乘积不溢出,t 必须为 0, 根据第三条,当且仅当 t 为 0 的时候 \(p / x = y\) 用程序表示就是 (!x || p / x == q) 这个逻辑被证明是正确的。

这样3也证明了,再看x=0的情况,x等于零的时候乘积为零肯定不会溢出嘛,所以这个程序是正确可靠的。证毕。

证明tmult_ok的正确性的更多相关文章

  1. 循环不变量loop invariant 与 算法的正确性

    在论述插入排序的正确性的时候, 书中引入了循环不变量的概念, 刚开始稍微有点不太明白, 早上查了一波资料之后决定把自己的理解记录下来. 什么是循环不变量 ? 在我看来, 所谓循环不变量的就是一个在循环 ...

  2. 证明:寝室分配问题是NPC问题

    P.NP.NPC.NP-hard P:多项式时间能够解决的问题的集合,比如最短路径问题是集合P的一个元素,而最短路径问题本身又是一个集合,因此P是集合的集合. NP:多项式时间内能够验证的问题的集合. ...

  3. RapidJSON 代码剖析(四):优化 Grisu

    我曾经在知乎的一个答案里谈及到 V8 引擎里实现了 Grisu 算法,我先引用该文的内容简单介绍 Grisu.然后,再谈及 RapidJSON 对它做了的几个底层优化. (配图中的<Grisù& ...

  4. 两个int的和判断溢出

    long a,b; cin>>a>>b; long i; i = a+b; if((i^a)<0 && (i^b)<0) cout<<& ...

  5. BZOJ1828 [Usaco2010 Mar]balloc 农场分配

    直接贪心,我们把线段按照右端点从小到大排序,然后一个个尝试插入即可... 来证明贪心的正确性: 不妨设贪心得到的答案集合为$S$,最优解的答案集合为$T$ 若$S$不是最优解,那么$S \not= T ...

  6. algorithm -- 插入排序

    插入排序是<算法导论>中第一个介绍的算法,详细分析了插入排序的原理,执行过程,证明了算法的正确性.同时也引出了算法分析和算法分析常用的方法. 此文对原文作个转述,检验学到的知识. 文中使用 ...

  7. Codeforces Round #173 (Div. 2)

    A. Bit++ 模拟. B. Painting Eggs 贪心,每个物品给使差值较小的那个人,根据题目的约数条件,可证明贪心的正确性. C. XOR and OR \(,,00 \to 00,01 ...

  8. M1M2总结

    这个学期很开心可以和一帮兄弟姐妹们一起做软件写代码,总体看下来真的是充满哦了艰辛和困苦.虽然我是负责软件测试的这一块的,但是看着他们辛苦的写代码我也很是为他们着急和心疼.毕竟,编译当头,数据库辅助,每 ...

  9. UOJ264 【NOIP2016】蚯蚓

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

随机推荐

  1. mysql中like用法

    like 的通配符有两种 %(百分号):代表零个.一个或者多个字符. _(下划线):代表一个数字或者字符. 1. name以"李"开头 where name like '李%' 2 ...

  2. 9.5---括号是否有效(CC150)

    leetcode原题: char temp ; Stack<Character> stack = new Stack<Character>();//error:Stack< ...

  3. c++ SOA Axis2c 编译安装

    Axis2C 安装过程 1设置环境变量 export AXIS2C_HOME=/usr/local/axis2c 2.下载源码包解压编译安装 cd axis2c-src-1.6.0 ./configu ...

  4. python 类修饰器

    1. 修改类函数. 场景: 如果要给一个类的所有方法加上计时,并打印出来.demo如下: # -*- coding:utf-8 -*- import time def time_it(fn): &qu ...

  5. keepalived和heartbeat区别

    <1>Keepalived使用的vrrp协议方式,虚拟路由冗余协议 (Virtual Router Redundancy Protocol,简称VRRP):Heartbeat是基于主机或网 ...

  6. 三大UML建模工具Visio、Rational Rose、PowerDesign的区别

    本文源自http://developer.51cto.com/art/201006/207993.htm UML建模工具Visio .Rational Rose.PowerDesign的比较   RO ...

  7. Git索引

    原文: http://gitbook.liuhui998.com/7_4.html git中的索引(index)是一个存放了排好序的路径的二进制文件(通常是.git/index), 每一个条目都附带有 ...

  8. html常用标签的使用方法

    1  html标题 <h1> to <h6> <!DOCTYPE html> <html lang="en"> <head&g ...

  9. Mybatis中的in查询和foreach标签

    Mybatis中的foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合. foreach元素的属性主要有 item,index,collection,open,separato ...

  10. ffmpeg-20160701-git-bin.7z

    ESC 退出 0 进度条开关 1 屏幕原始大小 2 屏幕1/2大小 3 屏幕1/3大小 4 屏幕1/4大小 S 下一帧 [ -2秒 ] +2秒 ; -1秒 ' +1秒 下一个帧 -> -5秒 f ...