证明tmult_ok的正确性
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 的值。
书中给出三条线索,分别给出这三条线索的证明即可证明这个函数的正确性。
- 证明: x和y的整数相乘结果可以被写成 \(x*y = p + t*2^w\) 形式, 当且仅当 t != 0 的时候,p溢出。
- 证明: p 可以被写成 \(p = x * q + r\), 其中\(|r| < |x|\).
- 证明: 当且仅当 \(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的正确性的更多相关文章
- 循环不变量loop invariant 与 算法的正确性
在论述插入排序的正确性的时候, 书中引入了循环不变量的概念, 刚开始稍微有点不太明白, 早上查了一波资料之后决定把自己的理解记录下来. 什么是循环不变量 ? 在我看来, 所谓循环不变量的就是一个在循环 ...
- 证明:寝室分配问题是NPC问题
P.NP.NPC.NP-hard P:多项式时间能够解决的问题的集合,比如最短路径问题是集合P的一个元素,而最短路径问题本身又是一个集合,因此P是集合的集合. NP:多项式时间内能够验证的问题的集合. ...
- RapidJSON 代码剖析(四):优化 Grisu
我曾经在知乎的一个答案里谈及到 V8 引擎里实现了 Grisu 算法,我先引用该文的内容简单介绍 Grisu.然后,再谈及 RapidJSON 对它做了的几个底层优化. (配图中的<Grisù& ...
- 两个int的和判断溢出
long a,b; cin>>a>>b; long i; i = a+b; if((i^a)<0 && (i^b)<0) cout<<& ...
- BZOJ1828 [Usaco2010 Mar]balloc 农场分配
直接贪心,我们把线段按照右端点从小到大排序,然后一个个尝试插入即可... 来证明贪心的正确性: 不妨设贪心得到的答案集合为$S$,最优解的答案集合为$T$ 若$S$不是最优解,那么$S \not= T ...
- algorithm -- 插入排序
插入排序是<算法导论>中第一个介绍的算法,详细分析了插入排序的原理,执行过程,证明了算法的正确性.同时也引出了算法分析和算法分析常用的方法. 此文对原文作个转述,检验学到的知识. 文中使用 ...
- Codeforces Round #173 (Div. 2)
A. Bit++ 模拟. B. Painting Eggs 贪心,每个物品给使差值较小的那个人,根据题目的约数条件,可证明贪心的正确性. C. XOR and OR \(,,00 \to 00,01 ...
- M1M2总结
这个学期很开心可以和一帮兄弟姐妹们一起做软件写代码,总体看下来真的是充满哦了艰辛和困苦.虽然我是负责软件测试的这一块的,但是看着他们辛苦的写代码我也很是为他们着急和心疼.毕竟,编译当头,数据库辅助,每 ...
- UOJ264 【NOIP2016】蚯蚓
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...
随机推荐
- Configuration
package edu.fzu.ir.util; import java.io.File; import java.io.FileInputStream; import java.io.FileNot ...
- TortoiseGit 添加邮箱 失败保存配置
解决方法 将保存至改为此版本库
- ThinkPHP 知识点链接
1.Thinkphp3.2 行为扩展和插件(Hook) http://www.thinkphp.cn/topic/21323.html 2.ThinkPHP3.1.3的单字母函数汇总 ...
- Jquery Ajax处理,服务端三种页面aspx,ashx,asmx的比较
常规的Jquery Ajax 验证登录,主要有3种服务端页面相应 ,也就是 aspx,ashx,asmx即webserivice . 下面分别用3种方式来(aspx,ashx,asmx)做服务端来处理 ...
- IPC---共享内存
共享内存就是允许两个或多个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据时,不需要在客户进程和服务器进程之间幅值,因此是最快的一种IPC.不同进程之间共享的内存通常安 ...
- centos7时间同步和时区设置
centos7时间同步和时区设置 安装ntp服务的软件包 sudo yum install ntp 将ntp服务设置为缺省启动 systemctl enable ntpd 修改启动参数,增加-g -x ...
- linux自动定时备份web程序和mysql数据库
前些天受朋友说linux定时备份不知道怎么搞,叫帮忙处理一下.由于这段时间正闲着,所以也就欣然答应.由于朋友对linux不懂也希望我将操作的过程记录下来,也就是越详细越好.所以写得比较$%^& ...
- MySQL表中数据的迁移
INSERT INTO `crm_attachment`(OPERATOR_ID,ATTACHMENT_ID,TYPE ) SELECT APPLICATION_ID ,ATTACHMENT_ID,' ...
- hdu 1014.Uniform Generator 解题报告
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1014 题目意思:给出 STEP 和 MOD,然后根据这个公式:seed(x+1) = [seed(x) ...
- 跨浏览器的事件对象-------EventUtil 中的方法及用法
什么是EventUti----封装好的事件对象 在JavaScript中,DOM0级.DOM2级与旧版本IE(8-)为对象添加事件的方法不同 为了以跨浏览器的方式处理事件,需要编写一段“通用代码”,即 ...